Skip to content

onBeforeContextMenu never fires for a synthetic OSR right-click (root cause not yet isolated) #17

Description

@Thrameos

Summary

CefContextMenuHandler.onBeforeContextMenu never fires in response to a synthetic right-click dispatched to an OSR browser's UI component -- confirmed on this fork's current CEF version (146.0.10+g8219561+chromium-146.0.7680.179).

Root cause not yet isolated -- this issue is filed to keep a reproducer on record (per this fork's practice of tracking real findings, even partial ones) rather than because the exact mechanism is understood.

Repro

Added java/tests/junittests/CefContextMenuTest.java (currently @Disabled with a link to this issue -- remove @Disabled to re-run it):

  1. CefBrowserOsr's GLCanvas does register a real MouseListener that forwards every AWT MouseEvent to sendMouseEvent()/native CEF (confirmed by reading CefBrowserOsr.java), so the mechanism this test relies on is real.
  2. Dispatch a synthetic BUTTON3 press+release MouseEvent via Component.dispatchEvent() to browser.getUIComponent(), right after onLoadingStateChange reports the page finished loading.
  3. Expected: onBeforeContextMenu fires with non-null params/model. Actual: it never fires -- the test hangs for the full 30s until the test harness's own watchdog force-closes it (a clean, bounded failure, not an unrecoverable hang).

Plausible causes, not yet confirmed

  • The OSR canvas may need to have completed its first real GL paint before a dispatched event is processed as a genuine screen-position click -- this repro dispatches immediately after onLoadingStateChange, which may be too early for the GL surface to be realized.
  • CEF's context-menu trigger logic may key off exact modifier/click-count semantics (e.getModifiersEx(), getClickCount()) not fully replicated by a bare Component.dispatchEvent() the way a real OS-level event would carry them.
  • Possibly related to the same class of "synthetic input doesn't count" issues already found this session (onBeforePopup/issue JCEF doesn't expose CefExecuteJavaScriptWithUserGestureForTests, blocking real onBeforePopup test coverage #11, file-dialog trigger, download trigger) -- though those are specifically about user gesture requirements for navigation/download/dialog APIs, and it's unconfirmed whether context-menu triggering has an analogous requirement.

Suggested next steps

  • Try dispatching from inside a confirmed-first-paint callback (e.g. after CefRenderHandler.onPaint has fired at least once) rather than immediately on load completion.
  • Compare the exact MouseEvent fields a real OS-generated right-click carries (via manual/interactive testing) against what this synthetic one sets, to find a field-level mismatch.

Found via

This fork's coverage-expansion effort (tracked in #5) -- CefContextMenuParams_N.cpp/CefMenuModel_N.cpp are the single largest remaining 0%-covered chunk (481 lines combined) per a real gcovr measurement, and this was the natural next test to attempt.

Activity

  1. added a commit that references this issue on Aug 29, 2026
  2. Thrameos commented on Aug 30, 2026

    @Thrameos
    OwnerAuthor

    Root-caused and fixed -- this was never a JCEF/CEF bug, just three compounding test-technique gaps in how the synthetic right-click was constructed:

    1. Wrong modifier field: the synthetic MouseEvent's modifiers constructor argument was 0. native/CefBrowser_N.cpp's GetCefModifiers() reads getModifiersEx() (the extended modifier mask), not the deprecated getModifiers() -- and MouseEvent's legacy constructor does NOT auto-populate getModifiersEx() from the button argument alone. Confirmed via a standalone repro. Fix: pass InputEvent.BUTTON3_DOWN_MASK.
    2. Missing focus: real interactive use gives the OSR canvas AWT input focus before any click reaches it -- CefBrowserOsr registers a FocusListener that calls browser.setFocus(true) on FOCUS_GAINED, which reaches CEF's own internal WebContents focus. Confirmed by reading CEF's own reference OSR implementation (tests/cefclient/browser/browser_window_osr_gtk.cc's ClickEvent(), which calls gtk_widget_grab_focus() on every mouse-down). Component.dispatchEvent() bypasses AWT's focus-transfer machinery entirely, so browser.setFocus(true) must be called explicitly.
    3. Dispatched too early: the click was fired immediately in onLoadingStateChange, before the OSR GL surface had a chance to realize/paint. A short delay (500ms) before dispatch was needed.

    With all three fixed, onBeforeContextMenu fires reliably (verified across many isolated runs). CefMenuModel.clear() is called inside the callback to suppress the real native popup CEF would otherwise show, avoiding a genuine "modal UI blocks teardown" hang risk (same class as #12).

    This unblocked the single largest remaining 0%-covered code in the fork: CefMenuModel_N.cpp went 3% → 84%, CefContextMenuParams_N.cpp went 13% → 79%, context_menu_handler.cpp went 0% → 62%. Total native coverage jumped 48.2% → 55% from this one fix. See CefContextMenuTest.java in the fork for the working repro/technique.

  3. added 6 commits that reference this issue on Aug 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions