Skip to content

fix(web): prevent Safari IME composition Enter from sending message#1140

Merged
ilblackdragon merged 2 commits intonearai:stagingfrom
micsama:fix/safari-ime-composition
Mar 15, 2026
Merged

fix(web): prevent Safari IME composition Enter from sending message#1140
ilblackdragon merged 2 commits intonearai:stagingfrom
micsama:fix/safari-ime-composition

Conversation

@micsama
Copy link
Copy Markdown
Contributor

@micsama micsama commented Mar 13, 2026

Fixes #1139

Problem

On Safari (macOS), pressing Enter to confirm CJK (Chinese/Japanese/Korean) IME input in the chat textarea sends the message immediately instead of just committing the composed text.

Root cause: Safari fires compositionend before keydown — the opposite of Chrome and Firefox. By the time the keydown handler runs, e.isComposing is already false, so the existing guard is bypassed.

Reference: WebKit bug 165004

Fix

Safari sets e.keyCode to 229 (VK_PROCESS) on every keydown event processed by the IME, including the confirmation Enter. This value is defined in the W3C UIEvents spec as the IME-processing sentinel and is never generated by a physical key on any keyboard layout.

- if (e.key === 'Enter' && !e.shiftKey && !e.isComposing) {
+ // keyCode 229 (VK_PROCESS) filters out IME-handled Enter on Safari, where
+ // compositionend fires before keydown leaving e.isComposing already false.
+ if (e.key === 'Enter' && !e.shiftKey && !e.isComposing && e.keyCode !== 229) {

Impact

  • Safari + CJK IME: IME confirmation Enter no longer sends the message ✓
  • Chrome / Firefox: e.isComposing already handles these correctly; keyCode !== 229 is a no-op ✓
  • All keyboard layouts / locales: keyCode 229 is never produced by a physical key; no regression risk ✓

Test Plan

  • macOS Safari — type with Chinese/Japanese/Korean input method, press Enter to confirm candidate → message should NOT send
  • macOS Safari — press Enter normally (no IME active) → message should send
  • Chrome / Firefox — same two cases above → behavior unchanged

@github-actions github-actions bot added scope: channel/web Web gateway channel size: XS < 10 changed lines (excluding docs) labels Mar 13, 2026
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves a browser-specific bug affecting Safari users who utilize CJK Input Method Editors (IMEs). It ensures that the 'Enter' key, when used to confirm IME composition, no longer prematurely sends a message, aligning Safari's behavior with other browsers like Chrome and Firefox. The fix specifically targets Safari's unique event firing order for compositionend and keydown events.

Highlights

  • Safari IME Composition Fix: Addressed an issue in Safari where pressing Enter to confirm CJK (Chinese/Japanese/Korean) IME input in the chat textarea would immediately send the message instead of just committing the composed text.
Changelog
  • src/channels/web/static/app.js
    • Modified the keydown event handler for the chat input to include an additional check for e.keyCode !== 229 to correctly handle IME confirmation on Safari.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions github-actions bot added risk: medium Business logic, config, or moderate-risk modules contributor: regular 2-5 merged PRs labels Mar 13, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request fixes a bug on Safari where confirming IME input with the Enter key incorrectly sends the chat message. The fix introduces a check for e.keyCode !== 229, which is a sentinel value used by Safari for IME-related key events. My review focuses on improving the maintainability of this workaround by suggesting the use of a named constant and enhancing the code comment with a reference to the underlying browser bug.

Comment thread src/channels/web/static/app.js Outdated
Comment on lines +1691 to +1692
// keyCode 229 (VK_PROCESS) filters out IME-handled Enter on Safari, where
// compositionend fires before keydown leaving e.isComposing already false.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Since keyCode is a deprecated property, it's helpful to include a permanent reference to the browser bug that necessitates this workaround. This provides valuable context for future maintainers and makes the comment more concise.

Suggested change
// keyCode 229 (VK_PROCESS) filters out IME-handled Enter on Safari, where
// compositionend fires before keydown leaving e.isComposing already false.
// Filter out IME composition confirmation on Safari. `isComposing` is not reliable
// as `compositionend` fires before `keydown`. See https://bugs.webkit.org/show_bug.cgi?id=165004

if (e.key === 'Enter' && !e.shiftKey && !e.isComposing) {
// keyCode 229 (VK_PROCESS) filters out IME-handled Enter on Safari, where
// compositionend fires before keydown leaving e.isComposing already false.
if (e.key === 'Enter' && !e.shiftKey && !e.isComposing && e.keyCode !== 229) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To improve readability and maintainability, consider extracting the magic number 229 into a named constant like const VK_PROCESS = 229;. This could be defined at a suitable scope (e.g., at the top of the file). The comment already helpfully mentions VK_PROCESS, and using a constant would make the code even clearer.

henrypark133
henrypark133 previously approved these changes Mar 13, 2026
Copy link
Copy Markdown
Collaborator

@henrypark133 henrypark133 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: Safari IME Enter handling looks correct

This is a tight fix for the Safari composition ordering edge case, and the change stays contained to the existing keydown path.

Positives:

  • The keyCode !== 229 guard directly targets the Safari IME-confirmation path without changing normal Enter behavior.
  • The PR is small enough that the manual test plan is proportionate.
  • Meaningful CI ran on the fork, so this is in a reasonable state to merge.

No blocking issues from my side.

Safari sets e.isComposing=false on the keydown event that ends IME
composition, unlike Chrome/Firefox. This caused pressing Enter to confirm
CJK input to immediately send the message.

Track composition state manually via compositionstart/compositionend and
guard the send condition with both e.isComposing and _isComposing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@micsama micsama force-pushed the fix/safari-ime-composition branch from b5760e4 to 25dfc5d Compare March 14, 2026 05:19
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@micsama
Copy link
Copy Markdown
Contributor Author

micsama commented Mar 14, 2026

Review: Safari IME Enter handling looks correct

This is a tight fix for the Safari composition ordering edge case, and the change stays contained to the existing keydown path.

Positives:

  • The keyCode !== 229 guard directly targets the Safari IME-confirmation path without changing normal Enter behavior.
  • The PR is small enough that the manual test plan is proportionate.
  • Meaningful CI ran on the fork, so this is in a reasonable state to merge.

No blocking issues from my side.

Updated the comment per the bot's suggestion — added a reference to the WebKit bug (165004) and rephrased for clarity. Skipped the named constant since VK_PROCESS is only used once and the comment already explains it.

Copy link
Copy Markdown
Collaborator

@zmanian zmanian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: Safari IME composition Enter fix

Clean, minimal fix for a well-known Safari/WebKit bug. Adding e.keyCode !== 229 is the standard workaround.

  • Safari fires compositionend before keydown, so e.isComposing is already false when Enter confirms CJK input
  • keyCode 229 (VK_PROCESS) identifies IME-handled keystrokes regardless of composition state
  • WebKit bug reference included: https://bugs.webkit.org/show_bug.cgi?id=165004
  • 3 lines changed, no risk

Title check: accurate.

LGTM.

@ilblackdragon ilblackdragon merged commit a70e58f into nearai:staging Mar 15, 2026
19 checks passed
@micsama micsama deleted the fix/safari-ime-composition branch March 15, 2026 05:50
bkutasi pushed a commit to bkutasi/ironclaw that referenced this pull request Mar 28, 2026
…earai#1140)

* fix(web): handle Safari IME composition Enter key

Safari sets e.isComposing=false on the keydown event that ends IME
composition, unlike Chrome/Firefox. This caused pressing Enter to confirm
CJK input to immediately send the message.

Track composition state manually via compositionstart/compositionend and
guard the send condition with both e.isComposing and _isComposing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(web): improve Safari IME comment with WebKit bug reference

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
drchirag1991 pushed a commit to drchirag1991/ironclaw that referenced this pull request Apr 8, 2026
…earai#1140)

* fix(web): handle Safari IME composition Enter key

Safari sets e.isComposing=false on the keydown event that ends IME
composition, unlike Chrome/Firefox. This caused pressing Enter to confirm
CJK input to immediately send the message.

Track composition state manually via compositionstart/compositionend and
guard the send condition with both e.isComposing and _isComposing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(web): improve Safari IME comment with WebKit bug reference

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor: regular 2-5 merged PRs risk: medium Business logic, config, or moderate-risk modules scope: channel/web Web gateway channel size: XS < 10 changed lines (excluding docs)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(web): Safari IME composition Enter key triggers message send

4 participants