Merge in Overlay Overhaul#2
Merged
Merged
Conversation
…ignore-injected-events to false (petoncle#66)
…e a new grid in when it replaces one mid fade-out
- **Grid drawn with Qt, with animations and styling**: The grid is now rendered with Qt, like the hints and the indicator, instead of the old GDI drawing. The grid has an optional transition animation when it moves or resizes, and configurable line opacity and background fill. The animation is enabled by default with a 100ms duration.
```properties
grid-mode.grid.transition-animation-enabled=true
grid-mode.grid.transition-animation-duration-millis=100
grid-mode.grid.fade-animation-enabled=true
grid-mode.grid.fade-animation-duration-millis=100
grid-mode.grid.line-opacity=1.0
grid-mode.grid.background-color=#FF0000
grid-mode.grid.background-opacity=0.1
```
https://github.com/user-attachments/assets/b395505e-9a06-4ec8-b361-81323c7b3fb4
- **Injected event fingerprinting**: mousemaster now tags its own injected input with a fingerprint, so it can tell its own events apart from events injected by other software (like kanata).
…ve hint grids hint.grid-cell-sizing=fit divides the hint area into exactly grid-max-row/column-count cells (pixel sizes ignored); grid-area=last-selected-hint-cell narrows the grid to the last selected cell. Together they enable neru-style recursive grids built as one mode per depth level. Adds neru.properties and an author.properties recursive-hint chain, plus a reference-doc note.
…tation paths at the nested cellSizing record In author configuration, hint3 zoomed would break.
Our Linux-only qt/ZoomWindow (now being retired in favor of the shared ScreenshotWidget from petoncle/main's overlay refactor) had a hardware-confirmed fix: clamp the zoom source rect to the captured pixmap's bounds and shrink the target rect by the same scale, so regions with no captured pixels stay black instead of leaving a transparent gap near screen edges/corners. ScreenshotWidget lacked this. Port it in before consolidating Linux onto this shared class, since Linux uses it as the sole, persistent zoom-rendering mechanism (no live-magnifier handoff like Windows has), so the gap would be visible in steady state rather than only during a brief transition.
Replace our hand-rolled qt/GridWindow, qt/HintMeshWindow, qt/ZoomWindow (deleted in the previous commit) with the same platform-agnostic GridRenderer, HintMeshRenderer, IndicatorRenderer, and ScreenshotWidget that WindowsOverlay now uses post-refactor. LinuxOverlay becomes a thin adapter: it owns the renderer instances, supplies TransparentWindow via the existing X11-flagged base class, and handles only X11-specific window management (real setTopmost() via Qt raise(), plus applying the same window flags to GridRenderer's/ScreenshotWidget's own widgets, which - being shared with Windows - only set FramelessWindowHint themselves and rely on the platform to add topmost/click-through styling, the way Windows does via native WS_EX_* calls). This fixes a real bug for free: our old HintMeshWindow silently dropped the Zoom parameter passed to setHintMesh(), which HANDOFF.md root-caused as the cause of second-level hint overlays rendering at screen-center instead of the zoomed location, and third-level/history-mode hints being unreadably small. HintMeshRenderer correctly transforms hint-box geometry by Zoom internally. It also adds a real mouse indicator to Linux for the first time - setIndicator()/hideIndicator() were previously complete no-op stubs. Since MouseController has no cursorVisualCenter()/mouseSize() lookup on Linux, a fixed cursor-size fallback is used for now (mirrors Windows' own fallback-when-lookup-fails pattern); a real XFixesGetCursorImage lookup is a follow-up. Active-screen resolution reuses the existing, already platform-agnostic ScreenManager.nearestScreenContaining() rather than adding new X11 code. The one-tick-deferred screenshot-capture mechanism for zoom (hide our own windows, grab the screen one tick later once the hide is actually flushed, since Linux has no capture-exclusion API like Windows' WDA_EXCLUDEFROMCAPTURE) is preserved, just re-targeted at the new renderers' windows instead of the old bespoke classes. LinuxPlatform gains lastMouseX()/lastMouseY() getters (exposing the XQueryPointer-polled position already tracked for Fix 4's mouse-move listener notifications) for the indicator glue, forwards mouse moves to LinuxOverlay.mouseMoved() for live indicator repositioning (Windows does this via its low-level hook; X11 has no such hook), and now calls overlay.setTopmost() on a periodic timer mirroring WindowsPlatform's own 200ms re-assertion against WMs that don't fully respect WindowStaysOnTopHint.
GridRenderer/HintMeshRenderer's hide() calls never actually unmap the underlying window - they only clear the drawn content and reset opacity, leaving the real window mapped indefinitely once first shown (GridRenderer's widget spans the entire virtual desktop; HintMeshRenderer's per-screen windows span entire screens). This is safe by design on Windows, where WS_EX_TRANSPARENT is applied once at HWND creation, making the window permanently click-through regardless of its "logical" visibility. The Linux port never added the Qt equivalent (WA_TransparentForMouseEvents), so the first time any grid or hint mesh was shown, its window became a permanent, invisible, full-desktop click blocker - swallowing every click (both our own synthetic XTestFakeButtonEvent clicks and real physical clicks) from that point forward, in every mode including idle-mode, until the process was killed. Fix: set WA_TransparentForMouseEvents in TransparentWindow's constructor (covers indicator + hint-mesh windows, both created via TransparentWindow) and in LinuxOverlay.applyX11OverlayFlags() (covers GridRenderer's widget and ScreenshotWidget, which are shared with Windows and don't extend TransparentWindow). Found via hardware testing: clicking (both program-driven and physical trackpad) stopped working entirely as soon as any hint or grid overlay had been shown once, in any mode afterward.
Qt's WA_TransparentForMouseEvents attribute (added in the previous commit) turned out not to be enough on its own for these frameless, override-redirect (X11BypassWindowManagerHint) windows - confirmed via hardware testing that clicks still didn't pass through. Add real, guaranteed click-through by clearing each overlay window's X11 input shape directly via the XShape extension (XShapeCombineRectangles with a null/empty rectangle list on ShapeInput) - the same mechanism compositors and other click-through overlay tools use, independent of Qt's platform-plugin behavior for this specific window configuration. Applied uniformly to all four overlay window types via applyX11OverlayFlags(): the indicator window, each per-screen hint mesh window (via a new createStyledHintMeshWindow() factory passed to HintMeshRenderer, mirroring WindowsOverlay's own factory pattern), GridRenderer's widget, and ScreenshotWidget.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.