mirror of
https://github.com/AquaMorph/dotfiles.git
synced 2026-11-03 08:17:59 +00:00
fix(window-focus): preserve single-click activation
This commit is contained in:
1 parent
9a3b37d5a8
commit
017bf12b43
4 files changed
+60
-17
No files matched your search
@@ -76,24 +76,20 @@ The script is safe to rerun but does not back up previous values or run
|
|||||||
automatically during `chezmoi apply`. Log out and back in if changes are not
|
automatically during `chezmoi apply`. Log out and back in if changes are not
|
||||||
visible.
|
visible.
|
||||||
|
|
||||||
### Hover window focus
|
### Window focus
|
||||||
|
|
||||||
AutoRaise focuses and raises windows on hover. Its settings are managed in
|
Hover focus is disabled in AeroSpace. Leave AutoRaise stopped so moving the
|
||||||
`~/.config/AutoRaise/config`.
|
pointer does not focus or raise windows:
|
||||||
|
|
||||||
After installing dependencies and applying the dotfiles, enable it at login:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
brew services start dimentium/autoraise/autoraise
|
|
||||||
```
|
|
||||||
|
|
||||||
Grant AutoRaise access in **System Settings → Privacy & Security → Accessibility**.
|
|
||||||
If it is not listed, use **+**, press **Cmd+Shift+G**, and enter the path printed by
|
|
||||||
`echo "$(brew --prefix autoraise)/bin/AutoRaise"`. Then restart it with
|
|
||||||
`brew services restart dimentium/autoraise/autoraise`.
|
|
||||||
|
|
||||||
Hold **Control** to temporarily suspend hover focus. To turn it off entirely:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
brew services stop dimentium/autoraise/autoraise
|
brew services stop dimentium/autoraise/autoraise
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Hammerspoon's `~/.hammerspoon/clickthrough.lua` focuses inactive windows on
|
||||||
|
mouse-down before passing through the original click, so the same click can
|
||||||
|
activate the clicked control. This is a workaround, not a native macOS setting;
|
||||||
|
some apps may still consume the first click. Modified clicks are left unchanged.
|
||||||
|
Use **Windows → Toggle single-click window activation** to disable it if an app
|
||||||
|
misbehaves. Hammerspoon needs Accessibility access and must be running.
|
||||||
|
|
||||||
|
Optional AutoRaise settings remain in `~/.config/AutoRaise/config`.
|
||||||
@@ -9,7 +9,7 @@ default-root-container-layout = 'tiles'
|
|||||||
default-root-container-orientation = 'auto'
|
default-root-container-orientation = 'auto'
|
||||||
enable-normalization-flatten-containers = true
|
enable-normalization-flatten-containers = true
|
||||||
enable-normalization-opposite-orientation-for-nested-containers = true
|
enable-normalization-opposite-orientation-for-nested-containers = true
|
||||||
focus-follows-mouse.enabled = true
|
focus-follows-mouse.enabled = false
|
||||||
key-mapping.preset = 'qwerty'
|
key-mapping.preset = 'qwerty'
|
||||||
persistent-workspaces = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
|
persistent-workspaces = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
-- Focus on mouse-down, before macOS delivers the original click to the app.
|
||||||
|
-- Never synthesize an extra click: controls that accept first mouse must not fire twice.
|
||||||
|
local clickthrough = {}
|
||||||
|
local ax = require("hs.axuielement")
|
||||||
|
local log = hs.logger.new("clickthrough", "warning")
|
||||||
|
|
||||||
|
local function focusClickedWindow(event)
|
||||||
|
-- Leave modified clicks (context menus, background links, etc.) unchanged.
|
||||||
|
if next(event:getFlags()) then return false end
|
||||||
|
local element = ax.systemWideElement():elementAtPosition(event:location())
|
||||||
|
if not element then return false end
|
||||||
|
local role = element:attributeValue("AXRole")
|
||||||
|
if role == "AXMenu" or role == "AXMenuItem" or role == "AXMenuBarItem"
|
||||||
|
or role == "AXMenuBar" then return false end
|
||||||
|
|
||||||
|
local windowElement = element:attributeValue("AXWindow")
|
||||||
|
if not windowElement and role == "AXWindow" then windowElement = element end
|
||||||
|
local window = windowElement and windowElement:asHSWindow()
|
||||||
|
if not window or not window:isStandard() then return false end
|
||||||
|
local focused = hs.window.focusedWindow()
|
||||||
|
if not focused or focused:id() ~= window:id() then window:focus() end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
clickthrough.tap = hs.eventtap.new({hs.eventtap.event.types.leftMouseDown}, function(event)
|
||||||
|
local ok, err = pcall(focusClickedWindow, event)
|
||||||
|
if not ok then log.w(tostring(err)) end
|
||||||
|
return false -- Always pass through the original click, including on errors.
|
||||||
|
end)
|
||||||
|
|
||||||
|
function clickthrough.toggle()
|
||||||
|
clickthrough.enabled = not clickthrough.enabled
|
||||||
|
if clickthrough.enabled then clickthrough.tap:start() else clickthrough.tap:stop() end
|
||||||
|
end
|
||||||
|
|
||||||
|
clickthrough.enabled = true
|
||||||
|
clickthrough.tap:start()
|
||||||
|
-- macOS can disable event taps after sleep or a slow accessibility response.
|
||||||
|
clickthrough.watchdog = hs.timer.doEvery(5, function()
|
||||||
|
if clickthrough.enabled and not clickthrough.tap:isEnabled() then
|
||||||
|
clickthrough.tap:start()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
return clickthrough
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
-- Placement rules inferred from the running windows on this Mac.
|
-- Placement rules inferred from the running windows on this Mac.
|
||||||
require("hs.ipc")
|
require("hs.ipc")
|
||||||
|
local clickthrough = require("clickthrough")
|
||||||
|
|
||||||
local spaces = require("hs.spaces")
|
local spaces = require("hs.spaces")
|
||||||
local log = hs.logger.new("placement", "info")
|
local log = hs.logger.new("placement", "info")
|
||||||
@@ -190,6 +191,7 @@ windowPlacement = {
|
|||||||
}
|
}
|
||||||
windowPlacement.menu:setTitle("Windows")
|
windowPlacement.menu:setTitle("Windows")
|
||||||
windowPlacement.menu:setMenu({
|
windowPlacement.menu:setMenu({
|
||||||
|
{title = "Toggle single-click window activation", fn = clickthrough.toggle},
|
||||||
{title = "Reapply placement rules", fn = restore},
|
{title = "Reapply placement rules", fn = restore},
|
||||||
{title = "Reload configuration", fn = hs.reload},
|
{title = "Reload configuration", fn = hs.reload},
|
||||||
{title = "Open Console", fn = hs.openConsole},
|
{title = "Open Console", fn = hs.openConsole},
|
||||||
|
|||||||
Reference in new issue
Block a user