Some checks are pending
Tests & Quality Checks / Test on Python 3.11 (push) Waiting to run
Tests & Quality Checks / Test on Python 3.12 (push) Waiting to run
Tests & Quality Checks / Test on Python 3.11-1 (push) Waiting to run
Tests & Quality Checks / Test on Python 3.12-1 (push) Waiting to run
Tests & Quality Checks / Test on Python 3.10 (push) Waiting to run
Tests & Quality Checks / Test on Python 3.11-2 (push) Waiting to run
Tests & Quality Checks / Test on Python 3.12-2 (push) Waiting to run
Tests & Quality Checks / Build Artifacts (push) Blocked by required conditions
Tests & Quality Checks / Build Artifacts-1 (push) Blocked by required conditions
194 lines
7.4 KiB
Markdown
194 lines
7.4 KiB
Markdown
# 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)
|