# 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 ✅ 1. **Checkbox hover effects** - Checkboxes appear on hover - CSS-based simulation via `.__mouse_hover` class works correctly - `input[type="checkbox"].__mouse_hover` CSS selector successfully applied 2. **Event detection** - Mouse position tracking: Working - `document.elementFromPoint()` polling: Working (50ms interval) - `mouseover`, `mouseenter`, `mouseleave`, `mousemove` event dispatching: Working - Angular event listeners: Receiving dispatched events correctly 3. **DOM element access** - Menu element found with `querySelectorAll()` - Event listeners identified: `{click: Array(1)}` - Not in Shadow DOM (accessible from JavaScript) #### What Doesn't Work ❌ 1. **Menu expansion via Tailwind :hover** - Menu element: `.group` class with `hover:bg-neutral-300` - Menu children have: `.group-hover:w-full` (Tailwind pattern) - Expected behavior: `.group:hover > .group-hover:w-full` triggers on hover - Actual behavior: No expansion (`:hover` pseudo-selector not activated) 2. **Tailwind CSS :hover-based styles** - Pattern: `.group:hover > .group-hover:*` (Tailwind generated) - Root cause: Qt doesn't properly set `:hover` pseudo-selector state for dispatched events - Impact: Any CSS rule depending on `:hover` pseudo-selector won't work ## 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: ```javascript 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: 1. User moves mouse 2. Browser kernel detects native hover 3. `:hover` pseudo-selector activates 4. CSS rules matching `:hover` are 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: 1. **Click events**: Directly handled by JavaScript listeners → Works 2. **Hover effects**: Rely on CSS `:hover` pseudo-selector → Doesn't work in Qt ### Why This Is a Limitation This is not fixable by JavaScript injection because: 1. **JavaScript can't activate CSS `:hover`**: The `:hover` pseudo-selector is a browser-native feature that only CSS engines can modify. JavaScript can't directly trigger it. 2. **Tailwind CSS is static**: Tailwind generates CSS rules like `.group:hover > .group-hover:w-full { width: 11rem; }`. These rules expect the `:hover` pseudo-selector to be active—JavaScript can't force them to apply. 3. **Qt engine limitation**: Qt WebEngineView's Chromium engine doesn't properly handle `:hover` for 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](../src/webdrop_bridge/ui/mouse_event_emulator.js) **What it does:** 1. Polls `document.elementFromPoint()` every 50ms to detect element changes 2. Dispatches `mouseover`, `mouseenter`, `mouseleave`, `mousemove` events 3. Applies `.__mouse_hover` CSS class for custom hover simulation 4. Works for elements with JavaScript event handlers **What it doesn't do:** 1. Cannot activate `:hover` pseudo-selector 2. Cannot trigger Tailwind CSS hover-based rules 3. 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 1. Open web app in Chrome 2. Hover over menu → Menu expands ✅ 3. Hover over checkbox → Checkbox appears ✅ ### Qt Test 1. Run application in Qt 2. Hover over menu → Menu does NOT expand ❌ (known limitation) 3. Hover over checkbox → Checkbox appears ✅ (works via CSS class) ### Debug Verification (if needed) In Chrome DevTools console: ```javascript // 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 1. **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 2. **Workarounds for your web app** - Replace `:hover` with JavaScript click handlers - Add click-to-toggle functionality instead of hover - This is outside the scope of WebDrop Bridge 3. **For similar Qt projects** - Be aware of this `:hover` pseudo-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 ### Future Improvements (Not Feasible) The following would require Qt framework modifications: - Improving QWebEngineView's `:hover` pseudo-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)