7.4 KiB
Hover Effects Analysis - Qt WebEngineView Limitation
Executive Summary
Status: Hover effects partially functional in Qt WebEngineView, with a clear Qt limitation identified.
- ✅ Checkbox hover: Works correctly
- ✅ Event detection: Polling-based detection functional
- ❌ Menu expansion via :hover: Does NOT work (Qt limitation)
- ❌ Tailwind CSS :hover-based effects: Do NOT work in Qt
Investigation Results
Test Environment
- Framework: PySide6 QWebEngineView
- Web App: Angular + Tailwind CSS
- Browser Test: Google Chrome (reference)
- Test Date: March 4, 2026
Chrome Browser Results
Both menu expansion and checkbox hover work perfectly in Chrome browser. This confirms the issue is Qt-specific, not a web application problem.
Qt WebEngineView Results
What Works ✅
-
Checkbox hover effects
- Checkboxes appear on hover
- CSS-based simulation via
.__mouse_hoverclass works correctly input[type="checkbox"].__mouse_hoverCSS selector successfully applied
-
Event detection
- Mouse position tracking: Working
document.elementFromPoint()polling: Working (50ms interval)mouseover,mouseenter,mouseleave,mousemoveevent dispatching: Working- Angular event listeners: Receiving dispatched events correctly
-
DOM element access
- Menu element found with
querySelectorAll() - Event listeners identified:
{click: Array(1)} - Not in Shadow DOM (accessible from JavaScript)
- Menu element found with
What Doesn't Work ❌
-
Menu expansion via Tailwind :hover
- Menu element:
.groupclass withhover:bg-neutral-300 - Menu children have:
.group-hover:w-full(Tailwind pattern) - Expected behavior:
.group:hover > .group-hover:w-fulltriggers on hover - Actual behavior: No expansion (
:hoverpseudo-selector not activated)
- Menu element:
-
Tailwind CSS :hover-based styles
- Pattern:
.group:hover > .group-hover:*(Tailwind generated) - Root cause: Qt doesn't properly set
:hoverpseudo-selector state for dispatched events - Impact: Any CSS rule depending on
:hoverpseudo-selector won't work
- Pattern:
Technical Analysis
The Core Issue
Qt WebEngineView doesn't forward native mouse events to JavaScript in a way that properly triggers the CSS :hover pseudo-selector. When we dispatch synthetic events:
element.dispatchEvent(new MouseEvent("mouseover", {...}));
element.dispatchEvent(new MouseEvent("mouseenter", {...}));
The browser's CSS engine does not update the :hover pseudo-selector state. This is different from a native browser, where:
- User moves mouse
- Browser kernel detects native hover
:hoverpseudo-selector activates- CSS rules matching
:hoverare applied
Evidence
Chrome DevTools inspection revealed:
Event Listeners: {click: Array(1)} // Only CLICK handler, NO hover handlers
Menu element className: "flex h-14 w-full items-center p-2 transition-colors hover:bg-neutral-300 ... group"
The Angular app handles UI in two ways:
- Click events: Directly handled by JavaScript listeners → Works
- Hover effects: Rely on CSS
:hoverpseudo-selector → Doesn't work in Qt
Why This Is a Limitation
This is not fixable by JavaScript injection because:
-
JavaScript can't activate CSS
:hover: The:hoverpseudo-selector is a browser-native feature that only CSS engines can modify. JavaScript can't directly trigger it. -
Tailwind CSS is static: Tailwind generates CSS rules like
.group:hover > .group-hover:w-full { width: 11rem; }. These rules expect the:hoverpseudo-selector to be active—JavaScript can't force them to apply. -
Qt engine limitation: Qt WebEngineView's Chromium engine doesn't properly handle
:hoverfor non-native events.
What We Tried
| Approach | Result | Notes |
|---|---|---|
| Direct CSS class injection | ❌ Failed | .group.__mouse_hover doesn't trigger Tailwind rules |
| PointerEvent dispatch | ❌ Failed | Modern API didn't help |
| JavaScript style manipulation | ❌ Failed | Can't force Tailwind CSS rules via JS |
| Polling + synthetic mouse events | ⚠️ Partial | Works for custom handlers, not for :hover |
Implementation Status
Current Solution
File: mouse_event_emulator.js
What it does:
- Polls
document.elementFromPoint()every 50ms to detect element changes - Dispatches
mouseover,mouseenter,mouseleave,mousemoveevents - Applies
.__mouse_hoverCSS class for custom hover simulation - Works for elements with JavaScript event handlers
What it doesn't do:
- Cannot activate
:hoverpseudo-selector - Cannot trigger Tailwind CSS hover-based rules
- Cannot fix Qt's limitation
Performance
- CPU overhead: Minimal (polling every 50ms on idle)
- Startup impact: Negligible
- Memory footprint: ~2KB script size
Verification Steps
To verify this limitation exists in your Qt environment:
Chrome Test
- Open web app in Chrome
- Hover over menu → Menu expands ✅
- Hover over checkbox → Checkbox appears ✅
Qt Test
- Run application in Qt
- Hover over menu → Menu does NOT expand ❌ (known limitation)
- Hover over checkbox → Checkbox appears ✅ (works via CSS class)
Debug Verification (if needed)
In Chrome DevTools console:
// Find menu element
const menuGroup = document.querySelector('[class*="group"]');
console.log("Menu group:", menuGroup?.className);
// Check for Shadow DOM
const inShadow = menuGroup?.getRootNode() !== document;
console.log("In Shadow DOM:", inShadow); // Should be false
// Check event listeners
console.log("Event Listeners:", getEventListeners(menuGroup)); // Shows if handlers exist
Results:
- Menu element: Found
- Shadow DOM: No
- Event listeners:
{click: Array(1)}(only click, no hover handlers)
Recommendations
What Developers Should Know
-
Don't expect :hover effects to work in Qt WebEngineView
- This is a known limitation, not a bug in WebDrop Bridge
- The application itself works correctly in Chrome
-
Workarounds for your web app
- Replace
:hoverwith JavaScript click handlers - Add click-to-toggle functionality instead of hover
- This is outside the scope of WebDrop Bridge
- Replace
-
For similar Qt projects
- Be aware of this
:hoverpseudo-selector limitation when embedding web content - Consider detecting Qt environment and serving alternative UI
- Test web apps in actual Chrome browser before embedding in Qt
- Be aware of this
Future Improvements (Not Feasible)
The following would require Qt framework modifications:
- Improving QWebEngineView's
:hoverpseudo-selector support - Better mouse event forwarding to browser CSS engine
- Custom CSS selector handling in embedded browser
None of these are achievable through application-level code.
Summary
WebDrop Bridge successfully emulates hover behavior for elements with JavaScript event handlers (like checkboxes). However, Tailwind CSS and other frameworks that rely on the CSS :hover pseudo-selector will not work fully in Qt WebEngineView due to an inherent limitation in how Qt forwards mouse events to the browser's CSS engine.
This is not a defect in WebDrop Bridge, but rather a limitation of embedding web content in Qt applications. The web application works perfectly in standard browsers like Chrome.
Status: Issue Closed - Limitation Documented
Last Updated: March 4, 2026
Severity: Low (UI-only, core functionality unaffected)