Skip to content

Add Taskbar Auto-Hide Trigger Zone v1.0.0#4610

Open
bushbellbest wants to merge 1 commit into
ramensoftware:mainfrom
bushbellbest:main
Open

Add Taskbar Auto-Hide Trigger Zone v1.0.0#4610
bushbellbest wants to merge 1 commit into
ramensoftware:mainfrom
bushbellbest:main

Conversation

@bushbellbest

Copy link
Copy Markdown

Adds a configurable wider trigger zone for the Windows 11 auto-hidden taskbar.

When the mouse pointer enters the configured edge zone, the matching taskbar is revealed and remains visible while the pointer stays within that zone. When the pointer leaves the zone, normal Windows auto-hide behavior resumes.

The physical cursor is not moved. The mod provides a virtual pointer-over state only to the matching taskbar.

Features:

  • Configurable trigger margin in pixels
  • Tested with 100 px, 250 px, and 500 px trigger margins
  • Keeps the taskbar visible while the cursor remains in the configured trigger zone
  • Supports primary and secondary taskbars
  • Supports taskbars positioned at the bottom, top, left, or right edge
  • Does not replace or modify Explorer's native taskbar timer IDs
  • Uses UI-thread taskbar transitions for Explorer operations

Tested on:

  • Windows 11 build 26200.8655
  • Windhawk 1.7.3
  • Taskbar auto-hide enabled

Changelog

N/A — new mod.

Mod authorship

If this pull request introduces a new mod, please complete the section below.

This mod was created by:

    • The submitter, without AI assistance
    • The submitter, with AI assistance
    • ChatGPT
    • Claude
    • Gemini
    • Another AI (please specify): Codex
    • Other (please specify):

Please select the options that best apply. Your selection does not affect the acceptance criteria, but it helps reviewers understand the context of the code and provide relevant feedback.

Add Taskbar Auto-Hide Trigger Zone v1.0.0
@m417z

m417z commented Jun 29, 2026

Copy link
Copy Markdown
Member

Submission review

Note: This review was done by Claude, and then refined manually. Due to the amount of submissions, doing a fully manual review for each pull request is no longer feasible. Thank you for understanding.

Please address the following issues. The items in the collapsed sections are optional, so it's your call whether to address them.

A note regarding point 3: If we decide to keep it as a separate mod, I think having two mods with the names "Taskbar auto-hide custom activation area" and "Taskbar Auto-Hide Trigger Zone" is confusing.


1. The mod won't survive an Explorer restart / reboot. On a fresh explorer.exe start, Wh_ModInit runs before Explorer has loaded Taskbar.View.dll, so HookTaskbarViewSymbols() finds neither Taskbar.View.dll nor ExplorerExtensions.dll, returns false, and Wh_ModInit returns FALSE. Windhawk then only retries the mod on the next settings change — so after every reboot or Explorer crash the mod is silently dead until the user re-saves a setting. (The mod works the first time only because Explorer is already running when you enable it.)

Unlike taskbar.dll (which you correctly force-load from System32), Taskbar.View.dll can't be force-loaded early. The established pattern is to defer: if the view module isn't present yet, don't fail init — hook LoadLibraryExW in kernelbase.dll and apply the view hooks when it loads, plus a retry in Wh_ModAfterInit. See taskbar-auto-hide-custom-activation-area for a copy-pasteable version:

2. Multi-monitor: holding one secondary taskbar visible holds all secondary taskbars visible. CSecondaryTray__AutoHide_Hook decides whether to block the native auto-hide with IsVirtualPointerOverKind(TaskbarKind::Secondary), which is true whenever any secondary taskbar is the active zone — it never compares the hook's own pThis to the active one:

static void WINAPI CSecondaryTray__AutoHide_Hook(void* pThis, bool param1) {
    if (IsVirtualPointerOverKind(TaskbarKind::Secondary)) {   // "any secondary", not "this one"
        ...
        return;
    }
    CSecondaryTray__AutoHide_Original(pThis, param1);
}

With two or more secondary monitors, putting the cursor in monitor A's trigger zone prevents monitor B's taskbar from auto-hiding too, so B stays revealed while the cursor is nowhere near it. (The primary TrayUI::_Hide hook is fine — there's only ever one primary.) Resolve pThis to its taskbar window and gate on that instance instead — e.g. look up the entry whose wndProcThis == pThis, get its hwnd, and check IsVirtualPointerOver(hwnd). Your ViewCoordinator_..._Hook already does the per-hwnd check correctly, so only the two _Hide/_AutoHide paths need fixing.

3. Consider building this on the existing auto-hide mod rather than as a new, heavier reimplementation. This sits squarely inside m417z's auto-hide taskbar family — in particular taskbar-auto-hide-custom-activation-area, which already "customizes the taskbar auto-hide activation area." That mod tunes the along-edge dimension (which portion of the edge unhides); yours tunes the perpendicular dimension (how far from the edge). They're different axes, so this isn't a strict duplicate — but the maintainer strongly prefers extending an existing mod over adding an adjacent one, and a "trigger depth" setting would be a natural fit there. Worth raising with the author (m417z) / proposing it on his repo before shipping a separate mod.

Beyond the catalog question, the existing mods are a useful blueprint because your approach is noticeably heavier and more fragile than it needs to be: custom-activation-area keeps the taskbar in the desired state purely by hooking the native expand decision (ViewCoordinator::UpdateIsExpanded / ShouldTaskbarBeExpanded / HandleIsPointerOverTaskbarFrameChanged), with no need to scan the object's memory for a vtable to recover the Unhide this, no blocking of TrayUI::_Hide / CSecondaryTray::_AutoHide, and no forced Unhide call. Your own comment ("prevents the immediate re-hide seen in v9.1") suggests the blocking hooks are there to fight the native logic that the cleaner interception point would let you ride instead. I'd strongly suggest re-deriving the "keep it revealed" half from that mod's UpdateIsExpanded hook; it'll be far more robust across Windows updates.

Optional improvements

Minor polish — none of this affects users, so it's your call.

  • Drop the custom Log wrapper and the logEnabled setting. Windhawk already has a per-mod logging on/off toggle and prefixes the mod name, so Wh_Log can be called directly (you already do in several places). The Log helper additionally takes a shared SRW lock on every call just to read the flag. Removing Log + logEnabled removes a setting, a lock, and ~15 lines.
  • Unused libraries in @compilerOptions. -lole32 and -lversion aren't needed — there are no COM (Co*) or version-info (GetFileVersionInfo/VerQueryValue) calls. #include <shellapi.h> is used (for the ABE_* constants), so keep that.
  • RegisterWindowMessage names hardcode .v9. (Windhawk.TaskbarAutoHideTriggerZone.v9.CaptureThis, etc.) — a development-version leftover. The values only need to be unique; consider keying them off WH_MOD_ID (as the reference mods do: L"Windhawk_captureThis_" WH_MOD_ID) so they're tied to the mod id rather than a stale "v9".
  • The unload "restore" is best-effort. SendLeaveToActiveTaskbar() uses PostMessage, so when you disable the mod while a taskbar is held visible, the restore may not run before the hooks are torn down, leaving the taskbar revealed until the next native mouse event. A cross-thread SendMessage here would restore it synchronously before teardown. (Only matters on unload, so optional.)
  • No visual in the README. The effect is behavioral, so a short GIF of the wider reveal zone in action would help users understand what the mod does.

Functionality notes

Non-critical observations about the feature behavior itself.

  • The 30 ms cursor poll runs continuously, even when it can't do anything. Revealing from a band wider than the native ~1px edge stroke genuinely needs cursor sampling (there's no native event for "cursor within N px of the edge"), so polling is a reasonable choice and I wouldn't block on it. Two refinements worth considering: (a) the worker polls regardless of whether taskbar auto-hide is even enabled — gating on the auto-hide state (SHAppBarMessage(ABM_GETSTATE) -> ABS_AUTOHIDE) avoids needless work and any interference when the mod's preconditions aren't met; (b) pollIntervalMs is really an implementation detail to expose as a user setting, and 30 ms (~33 Hz) is on the aggressive side for a default — 50–100 ms is likely indistinguishable in feel.
  • GuessTaskbarEdge is a distance heuristic. Width-vs-height reliably separates horizontal from vertical taskbars, but the top-vs-bottom / left-vs-right tiebreak can misclassify on unusual layouts (and an auto-hidden taskbar's GetWindowRect is its slid-off-screen rect). For the primary taskbar, SHAppBarMessage(ABM_GETTASKBARPOS) gives the edge directly; for secondaries the current approach is fine but worth keeping in mind if edge-detection bugs surface.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants