Fix: Invisible overlay blocking mouse clicks
Problem: The overlay window, even when fully transparent or visually hidden (opacity 0), was still intercepting mouse events. This created a 'dead zone' on the screen where users could not click through to applications behind the overlay. This occurred because the low-level window hook was answering 'HTCAPTION' to hit tests regardless of the UI state. Solution: 1. Modified 'WindowHook' to accept an 'enabled' state. 2. When disabled, 'WM_NCHITTEST' now returns 'HTTRANSPARENT', allowing the OS to pass the click to the window underneath. 3. Updated 'main.py' to toggle this hook state dynamically: - ENABLED when Recording or Processing (UI is visible/active). - DISABLED when Idling (UI is hidden/transparent). Result: The overlay is now completely non-intrusive when not in use.
This commit is contained in:
44
main.py
44
main.py
@@ -222,12 +222,23 @@ class WhisperApp(QObject):
|
||||
self.settings_root.setVisible(False)
|
||||
|
||||
# Install Low-Level Window Hook for Transparent Hit Test
|
||||
# We must keep a reference to 'self.hook' so it isn't GC'd
|
||||
# scale = self.overlay_root.devicePixelRatio()
|
||||
# self.hook = WindowHook(int(self.overlay_root.winId()), 500, 300, scale)
|
||||
# self.hook.install()
|
||||
|
||||
# NOTE: HitTest hook will be installed here later
|
||||
try:
|
||||
from src.utils.window_hook import WindowHook
|
||||
hwnd = self.overlay_root.winId()
|
||||
# Initial scale from config
|
||||
scale = float(self.config.get("ui_scale"))
|
||||
|
||||
# Current Overlay Dimensions
|
||||
win_w = int(460 * scale)
|
||||
win_h = int(180 * scale)
|
||||
|
||||
self.window_hook = WindowHook(hwnd, win_w, win_h, initial_scale=scale)
|
||||
self.window_hook.install()
|
||||
|
||||
# Initial state: Disabled because we start inactive
|
||||
self.window_hook.set_enabled(False)
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to install WindowHook: {e}")
|
||||
|
||||
def center_overlay(self):
|
||||
"""Calculates and sets the Overlay position above the taskbar."""
|
||||
@@ -531,6 +542,25 @@ class WhisperApp(QObject):
|
||||
self.bridge.update_status("Error")
|
||||
logging.error(f"Download Error: {err}")
|
||||
|
||||
@Slot(bool)
|
||||
def on_ui_toggle_request(self, is_recording):
|
||||
"""Called when recording state changes."""
|
||||
# Update Window Hook to allow clicking if active
|
||||
is_active = is_recording or self.bridge.isProcessing
|
||||
if hasattr(self, 'window_hook'):
|
||||
self.window_hook.set_enabled(is_active)
|
||||
|
||||
@Slot(bool)
|
||||
def on_processing_changed(self, is_processing):
|
||||
is_active = self.bridge.isRecording or is_processing
|
||||
if hasattr(self, 'window_hook'):
|
||||
self.window_hook.set_enabled(is_active)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
app = WhisperApp()
|
||||
app.run()
|
||||
|
||||
# Connect extra signal for processing state
|
||||
app.bridge.isProcessingChanged.connect(app.on_processing_changed)
|
||||
|
||||
sys.exit(app.run())
|
||||
|
||||
Reference in New Issue
Block a user