Skip to content

About

Native-style Windows taskbar quick pin dock for Windhawk with drag-to-pin, drag-to-unpin.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

Β 

History

17 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ“Œ Left Taskbar Quick Pin Dock

Your own mini app dock, tucked neatly to the left of the Start button.

Windhawk Mod Version Platform Build


Left Taskbar Quick Pin Dock β€” live demo

Pin any app with a drag. Click it to launch or focus. Drag it off to let it go. That's the whole idea β€” a fast, good-looking launcher that lives right inside your Windows 11 taskbar and remembers your apps across restarts.

⚠️ Only for Windows 11 with a centered taskbar

This mod supports Windows 11 only, and only when the taskbar is centered (the default) β€” i.e. the Start button sits in the middle. On a left-aligned (or otherwise repositioned) taskbar there is no room to the left of Start, so the dock detects the unsupported layout and stays hidden. Windows 10 is not supported.

πŸͺΆ Lightweight by design. One single-file C++ mod that runs as a Windhawk tool mod in its own windhawk.exe process β€” no extra DLLs, no background service, no installer, and a fault can't take the shell down with it. It never moves or resizes your taskbar; it simply floats a transparent dock on top of it.

Why you'll like it

  • 🎯 Your own list β€” completely separate from the taskbar's built-in pinned apps.
  • πŸ“¦ Pins anything β€” any .exe, not just Store apps or shortcuts.
  • πŸ–οΈ Drag to pin β€” just drop an app window onto the dock, no right-click menus.
  • ⚑ Click to launch or focus β€” brings a running app forward, or starts a fresh one.
  • ↔️ Reorder by dragging β€” rearrange icons live, with smooth animation.
  • πŸͺ’ Playful drag-off β€” a stretchy "rope" follows your icon; snap it to unpin, with a little dust-poof.
  • πŸ”’ Lock it β€” freeze the dock so a stray gesture never drops a pin.
  • πŸ–±οΈ Scroll through pins β€” hover and spin the mouse wheel to glide across your apps.
  • πŸͺŸ Frosted-glass look β€” an optional rounded, blurred panel.
  • πŸ’Ύ Remembers everything β€” survives Explorer restarts, sign-outs, and reboots.

Table of Contents

πŸ‘€ Part I β€” User Guide

Everything you need to actually use the dock. If you just want to pin apps, this is all you need β€” no tech knowledge required.

  1. What it does
  2. Get started in 30 seconds
  3. Every gesture, at a glance
  4. Pinning and unpinning
  5. Locking the dock
  6. Scrolling through lots of pins
  7. Settings β€” in plain English
  8. Tips & FAQ
  9. Troubleshooting
  10. Known limitations

πŸ› οΈ Part II β€” Developer Reference

How it works under the hood. You don't need any of this to use the dock β€” it's here for the curious and for contributors. It assumes you've read Part I, so it won't re-explain what a gesture does β€” only how it's built.

  1. Architecture at a glance
  2. Thread model & locking
  3. Startup & geometry stabilisation
  4. The overlay window
  5. App-identity resolver
  6. Drag & reorder state machines
  7. The drag rope (tether)
  8. The dust vanish effect
  9. Dynamic dock sizing & scrolling
  10. Rendering, glass & rounded corners
  11. Persistence
  12. Multi-monitor docks
  13. Safety guards & exclusions
  14. Hooks, build flags & dependencies
  15. Contributing
  16. Changelog
  17. License


πŸ‘€ Part I β€” User Guide

1. What it does

This mod adds a small, persistent icon dock right next to the Start button on your Windows 11 taskbar. Think of it as a personal shelf for the apps you open most.

It's your own list β€” it has nothing to do with the taskbar's built-in pinned apps, and it can hold any program (not just Store apps). You add apps by dragging, launch them with a click, and it quietly remembers them forever β€” even after a restart.

The dock floats on top of the taskbar as a see-through panel. It never resizes or moves your taskbar, and it stays neatly inside the taskbar's height.

How it works β€” at a glance

No need to read the whole guide β€” here's the whole idea in three little pictures.

Pinning an app πŸ“Œ

flowchart LR
    A["πŸ“‚ Open<br/>an app"] --> B["πŸ–οΈ Drag its window<br/>onto the dock"]
    B --> C["πŸ“Œ Icon lands<br/>in your dock"]
    C --> D["πŸ’Ύ Remembered β€”<br/>survives restarts"]
Loading

Clicking a pinned icon πŸ‘†

flowchart LR
    A["πŸ‘† Click a<br/>pinned icon"] --> B{"App already<br/>running?"}
    B -- "Yes" --> C["πŸͺŸ Bring its<br/>window to front"]
    B -- "No" --> D["⚑ Launch it<br/>fresh"]
Loading

Unpinning (drag it off) πŸ’¨

flowchart LR
    A["πŸ–οΈ Drag icon<br/>off the dock"] --> B["πŸͺ’ Rope<br/>stretches"]
    B --> C{"Pulled far<br/>enough?"}
    C -- "Yes" --> D["πŸ’¨ Rope snaps β€”<br/>icon poofs to dust"]
    D --> E["❌ Unpinned"]
    C -- "No" --> F["↩️ Springs back β€”<br/>stays pinned"]
Loading

2. Get started in 30 seconds

  1. Install the mod through Windhawk (search for taskbar-quick-pin, or load the .cpp file manually).
  2. The dock appears just left of Start. It starts empty β€” that's normal.
  3. Open any app you want to keep handy (Notepad, Chrome, VS Code…).
  4. Drag that app's window (or its taskbar button) toward the dock. A little preview follows your cursor.
  5. Drop it on the dock. The icon fades and slides into place. πŸŽ‰
  6. From now on, click the icon any time to open or jump to that app.

⏳ First run β€” please be patient. On the very first launch the dock needs a moment to find the taskbar and settle, so it may not appear instantly. That's normal β€” it's working in the background. If it still hasn't shown up after a couple of minutes, restart Explorer (or, most reliably, your PC). You can also raise the Startup delay setting.


3. Every gesture, at a glance

You do this… …and this happens
Drag any app window or taskbar button onto the dock Pins the app
Left-click a pinned icon Focuses it if running, launches it if not
Drag a pinned icon left / right inside the dock Reorders it, live
Drag a pinned icon off the dock until the rope snaps Unpins it (with a dust poof)
Double-right-click a pinned icon Unpins it (off by default β€” turn on in settings)
Triple-click any icon quickly Unpins everything (opt-in β€” off by default)
Tap P three times quickly Pins the app you're currently using (opt-in β€” off by default)
Tap U three times quickly Unpins the app you're currently using (opt-in β€” off by default)
Tap L three times quickly Locks / unlocks the dock (opt-in β€” off by default)
Press the hotkey (default Ctrl + Alt + P) Pins or unpins the app you're currently using
Scroll the mouse wheel over the dock Glides the highlight across your pinned icons
Hover an icon It gently magnifies, macOS-style

The three-tap P / U / L shortcuts must land within about 0.6 seconds. The triple-click "unpin all" must land within about 1 second.


4. Pinning and unpinning

To pin an app, drag its window (or its taskbar button) onto the dock and let go. You can also:

  • Tap P three times quickly to pin whatever app you're using right now, or
  • Press the hotkey (Ctrl + Alt + P by default) to do the same.

To unpin one app, you have a few choices β€” pick whichever feels natural:

  • Drag it off the dock. A stretchy "rope" links the icon to your cursor. Pull far enough and the rope snaps β€” the icon bursts into dust and is gone. By default the icon stays put if you let go before the rope breaks (you can change this β€” see Unpin trigger in settings).
  • Double-right-click it (only if you've enabled that setting).
  • Tap U three times quickly to unpin the app you're currently using.
  • Press the hotkey while using an app that's already pinned β€” it toggles off.

To clear the whole dock, quickly triple-click any icon.

🧱 The dock only holds so many. By default it fits 5 apps, and you can raise this up to 20 in settings. If you try to add one when it's full, the dock briefly flashes to let you know.


5. Locking the dock

Worried about accidentally knocking an app off? Tap the L key three times quickly to lock the dock. Tap L three times again to unlock it.

While locked:

  • βœ… You can still pin new apps and reorder them.
  • 🚫 The quick gesture unpins are refused β€” triple-tap U, the triple-click "unpin all", double-right-click, and the hotkey's unpin all stop working, so a stray gesture can't drop a pin.
  • πŸͺ’ A deliberate drag-off that breaks the rope still unpins β€” that's a hard-to-do-by-accident action, so it's always allowed.

When you attempt something that's blocked, the dock gives a little glow flash to remind you it's locked.


6. Scrolling through lots of pins

The dock sizes itself to fit what you've actually pinned. Unpin a few and it shrinks; pin more and it grows β€” but it stops growing at 10 visible icons so it never hogs your taskbar.

Pin more than 10 and the extras don't make the dock wider. Instead, hover the dock and spin your mouse wheel to glide the highlight across all your apps (wheel down = next, wheel up = previous). The highlighted icon pops out like the macOS dock. This scroll-wheel navigation can be turned off in settings if you prefer.


7. Settings β€” in plain English

All settings live in the Windhawk settings panel under this mod. Most apply instantly ("live"); a couple need a mod reload, which is noted below.

Setting What it does Default
Max pinned apps How many apps you can pin, from 1 to 20. 5
Icon size How big each icon is (before your display scaling). 16–48. At 150% scaling, 33 looks like ~50 px. 33
Dock gap from Start How far the whole dock sits from the Start button, 0–40 px. 6
Show workspace divider Shows the gold divider between your workspace/folder pins and your app pins. Appears only when you have both. on
Hide dock outline Makes the thin grey outline Windows 11 draws around the dock (on all sides) invisible. On = no border; off = system default. Purely cosmetic; applies live. off
Drag to reorder Lets you drag icons left/right to rearrange them. Off = dragging an icon only unpins it. on
Double-right-click to unpin Unpin an icon by double-right-clicking it (with a dust effect). Off = normal right-click menu shows instead. off
Scroll-wheel navigation Hover + scroll to move the highlight across your pins. on
Drag tether (rope) Shows the stretchy thread while you drag an icon off to unpin. Turn off for a plain drag with no thread. on
Drag tether β€” thickness How thick the rope looks, 1 (hair-thin) to 10 (bold cord). 2
Drag tether β€” break length How far you pull before the rope snaps and unpins, 150–650 px. Lower = snaps sooner. 450
Unpin trigger When a drag-off actually unpins. 0 = only when the rope breaks (let go early and it springs back, staying pinned). 1 = rope breaks or you drop it anywhere off the dock. 0
Corner roundness Dock corner shape, 0–100. 0 = square, 1–40 = slightly rounded, 41–100 = fully rounded pill. Always smooth. 100
Explorer workspace pins Allow File Explorer to be dragged in as a special "workspace" pin. Off = Explorer is ignored. off
Multi-monitor dock Show a mirrored, read-only dock on each secondary monitor. Only the primary supports pinning. (Reload to apply.) off
Startup delay Extra wait before the dock loads, 0–3000 ms. Raise it if the dock appears in the wrong spot at login. 0
Sync with taskbar auto-hide Hide the dock along with the taskbar when auto-hide slides it off screen. off
Verbose debug logging Emit the high-frequency drag/reorder + debug traces to the Windhawk log. Leave off to keep the log quiet β€” only errors and key events are logged. Troubleshooting only. off
Pin hotkey β€” modifiers Which modifier keys to hold for the pin/unpin hotkey. Set to "Disabled" to switch the hotkey off. Ctrl + Alt
Pin hotkey β€” key Which key to press with the modifiers above. P

8. Tips & FAQ

Does this replace my normal taskbar pins? No. This dock is a completely separate list. Your Windows pinned apps stay exactly where they are.

Will the running dot tell me if an app is open? Yes β€” a small dot under an icon means that app has a window open, so a click will focus it. No dot means a click will launch it fresh.

Can I pin a portable .exe or a game launcher? Yes. Almost any real program works β€” it doesn't have to be a Store app or a Start-menu shortcut.

How do I change the hotkey? Set the modifiers and key separately in settings. Set modifiers to "Disabled" to turn the hotkey off entirely.

Where are my pins stored? In Windhawk's own per-mod storage (via Wh_SetStringValue / Wh_SetBinaryValue), tied to your user account, so they survive restarts β€” and they're removed automatically when you uninstall the mod, leaving nothing behind.


9. Troubleshooting

The dock didn't appear right away. On first launch it needs a moment to detect the taskbar. Wait a minute or two. If it's still missing, restart Explorer or your PC, and try raising the Startup delay setting.

The dock showed up in the wrong position. This usually means the taskbar was still loading. Raise Startup delay (e.g. to 1000–2000 ms). It self-corrects on most systems once the taskbar settles.

An app shows a generic/blank icon. A few apps use custom icon handlers that no Windows API can read reliably. This is a shell limitation, not a bug in the dock.

A dragged app got pinned as the wrong program. Some UWP apps briefly report their host process if their window isn't ready. Try dragging again once the app has fully opened.

My gesture didn't unpin anything. Check whether the dock is locked (you'll see a glow flash when you try). Tap L three times to unlock. Remember: while locked, only a rope-breaking drag-off unpins.

I saw two docks / clicks stopped working after opening a File Explorer window. Fixed in v2.5.1. Opening a pinned File Explorer window spawned a second explorer.exe that drew its own dock and fought the first for clicks. Update to 2.5.1 and reload the mod.

Clicking a pinned icon sometimes does nothing. Fixed in v2.5.1. A quick click right after another window took focus could be misread as "too slow" and dropped. In 2.5.1 a click is decided by movement, not timing, so every click launches or focuses. Update and reload the mod.


10. Known limitations

  • Windows 11 with a centered taskbar only. The dock lives in the gap to the left of a centered Start button. On a left-aligned taskbar that gap doesn't exist, so the mod detects the unsupported layout and hides the dock; switch Start back to centered to use it. Windows 10 is not supported.
  • Secondary-monitor docks are mirrored and read-only β€” Beta. Only the primary dock can pin/unpin.
  • A few apps show a generic Windows icon β€” a shell limitation; no Win32 API resolves every icon reliably.
  • Some UWP apps may resolve to their host process if their window isn't ready when you drag them.

Behavioural notes (tracked, not yet addressed)

These are known rough edges from the code review. They are not blocking and are documented here so the behaviour is expected rather than surprising:

  • English-only UI-string matching. Explorer integration (workspace pins, new-tab restore, tab/window-title matching) matches literal English UI strings such as File Explorer and New tab. On a non-English Windows these paths silently do nothing. A future fix would key off UIA AutomationIds where available instead of localised names.
  • Start-button detection is heuristic. Start is located by a loose class match (Start / InputSite) plus a left-half taskbar position guess, so on an unusual taskbar layout it can latch onto the wrong element.
  • Mixed-DPI multi-monitor sizing. All docks are sized from the primary taskbar's DPI, so on a mixed-DPI multi-monitor setup the mirror docks can be scaled for the wrong monitor. (Multi-monitor is already flagged Beta.)
  • Turning off multi-monitor docks needs a reload. Disabling the multiMonitorDock setting doesn't tear down docks already on secondary monitors; reload the mod (or restart Explorer) to clear them.
  • Per-frame region rebuild during dock glide. The rounded-corner window region is rebuilt every animation frame, which is cheap but not free; caching it is a tracked performance follow-up.
  • Bare-key P / U / L gestures react everywhere. When enabled (off by default), these poll the raw key state globally, so they fire in any focused app β€” including text and password fields. Prefer the Ctrl+Alt hotkeys unless you specifically want the bare-key gestures, and read the setting's warning. (Note: these gestures now run even before the dock's overlay window is up β€” see the changelog fix below β€” so enabling the setting is all that's required.)
  • Explorer workspace-restore is UIA-driven and slow. Restoring a folder group drives Explorer's UI through UI Automation with polling waits (up to a few seconds per tab) and is inherently fragile against Explorer UI changes; no faster public API exists today.

Fixed in this revision: the Layer-3 app-identity fallback now only resolves a window the cursor is actually inside (no more "wrong neighbouring app" pins); focus-if-running skips tool/untitled windows so it targets a real app window; and workspace IDs are now GUID-based, removing the same-second collision risk.



πŸ› οΈ Part II β€” Developer Reference

This half documents the implementation for contributors. It builds on Part I β€” features are referred to by name (rope, dust vanish, lock, scroll-nav…) rather than re-described.

11. Architecture at a glance

The mod is a single .cpp file compiled by Windhawk's embedded Clang toolchain. It runs as a Windhawk tool mod (@include windhawk.exe): a launcher instance spawns a dedicated windhawk.exe -tool-mod "taskbar-quick-pin" process and the real logic runs there via WhTool_ModInit / WhTool_ModSettingsChanged / WhTool_ModUninit β€” so it is not injected into explorer.exe and a fault can't take the shell down. It hooks no Win32 functions (aside from the tool-mod launcher's own entry-point hook). It discovers taskbar geometry by polling on its worker thread and registers its own overlay windows on a dedicated UI thread.

flowchart TB
    subgraph MAIN["🧡 Dedicated UI thread β€” g_uiThread"]
        direction TB
        OP["OverlayProc<br/>WM_PAINT Β· WM_NCHITTEST Β· WM_RBUTTONUP<br/>WM_HOTKEY Β· WM_MOUSEWHEEL"]
        WE["Owns every top-level window<br/>+ runs the GetMessageW / DispatchMessageW pump"]
    end
    subgraph WORK["🧡 Worker thread β€” g_workerThread"]
        direction TB
        IN["Input polling β€” 8–50 ms adaptive"]
        SM["Drag + reorder state machines"]
        FX["Rope (tether) + dust (vanish) animation"]
        AN["Per-icon animation β€” opacity, position, hover"]
        TT["Triple-tap P / U / L detection"]
    end
    CS[("πŸ”’ g_cs β€” CRITICAL_SECTION<br/>guards g_pinnedApps")]
    MAIN -->|all reads / writes| CS
    WORK -->|all reads / writes| CS
Loading

(GitHub renders the diagram above automatically.)

g_pinnedApps is the only shared mutable state; every access goes through g_cs. The scalar cross-thread globals (g_dragState, g_hoverIndex, g_iconsLocked, g_appScrollStart, g_scrollNavUntil) are std::atomic; the shared std::wstrings are guarded by g_cs. They are written by the worker and read by the UI thread only for display.

Key tunables (compile-time):

Constant Value Meaning
MIN_APP_SLOTS 5 Dock never shrinks below this
MAX_VISIBLE_APP_SLOTS 10 Dock never grows past this; extras scroll
MAX_WORKSPACE_PINS 2 Left-anchored Explorer workspace pins
KEY_TAP_WINDOW_MS 600 Window for the P / U / L triple-taps
RAPID_CLICK_WINDOW_MS 1000 Window for triple-click "unpin all"
RUNNING_STATE_CHECK_MS 500 Period between running-app scans
HOVER_SCALE_FACTOR 1.15 Hover magnify amount
VANISH_MS 900 Dust disintegration duration
SCROLL_NAV_LOCK_MS 700 How long a wheel-selected highlight is protected

12. Thread model & locking

Dedicated UI thread (g_uiThread, started from Wh_ModInit) registers all window classes against the mod's own module, creates every top-level window (input owner, overlay, ghost, tether, vanish, secondary docks), registers the pin hotkey, and runs the GetMessageW / DispatchMessageW pump. It processes all WM_* messages and, on teardown, destroys every window + hotkey and UnregisterClassWs all seven classes on the same thread that created them β€” so nothing is torn down from a foreign thread. It never does slow I/O.

Worker thread (g_workerThread, created in Wh_ModInit, exited via g_exitEvent) runs an adaptive polling loop (8 ms while active, 16 ms cool-down, 50 ms when idle). It owns the drag/reorder machines, all animation, the rope and dust effects, the triple-tap gestures, and the taskbar-geometry polling FSM.

Cross-thread rules:

  • g_pinnedApps β€” always under g_cs.
  • Overlay/ghost/tether/vanish windows are created on the dedicated UI thread; the worker only calls InvalidateRect, ShowWindow, and UpdateLayeredWindow on them (copy-under-lock, then call β€” never hold g_cs across a cross-thread send).
  • SavePinnedApps() snapshots paths under g_cs, then releases before writing to Windhawk mod storage (Wh_SetBinaryValue / Wh_SetStringValue).
  • The double-right-click unpin hands the dust request to the worker via interlocked globals (g_vanishReq*), because all vanish GDI must run on the worker thread.
  • g_secondaryDocks has its own dedicated lock (the worker iterates it in RepaintSecondaryDocks).

13. Startup & geometry stabilisation

The taskbar's exact size isn't known at injection. RefreshTaskbarCache() drives a three-state FSM on the worker thread:

STATE_BOOT  β†’  first valid width  β†’  STATE_STABILISING  β†’  two stable reads (Β±10 px)  β†’  STATE_STABLE

On each transition that commits a new g_dockLocalW, ReseatIconPositions() recomputes every icon's targetX/currentX. Without it, icons loaded from Windhawk mod storage (which start at position 0, before the width is known) would pile up at the left until the first pin/unpin. startupDelay adds an optional pre-init wait for slow logins.


14. The overlay window

WS_POPUP + WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW, HWND_TOPMOST. It is exactly the dock's width and the taskbar's height, right-edge aligned to Start (minus dockGapFromStart).

  • WM_NCHITTEST returns HTCLIENT only over icon slots (via HitTestIcon), HTTRANSPARENT elsewhere β€” so the taskbar underneath keeps receiving all other input.
  • WM_PAINT double-buffers through g_alphaBlendDC.
  • WM_RBUTTONUP implements double-right-click unpin (respects the lock and the enable setting).
  • WM_HOTKEY toggles the focused app's pin (respects the lock for the unpin direction).
  • WM_MOUSEWHEEL drives scroll-nav highlight paging.

15. App-identity resolver

Identifying which app is under the cursor at mouse-down runs a layered pipeline:

  • Layer 0 β€” dock hit test: cursor over an existing icon uses that slot's exePath (reorder / unpin path).
  • Layer 1 β€” UI Automation: IUIAutomation::ElementFromPoint β†’ NativeWindowHandle / AUMID (kAumidPropId = 30113) β†’ process path. Resolves UWP and grouped taskbar buttons.
  • Layer 2 β€” WindowFromPoint fallback: raw window β†’ PID β†’ path. Returns NULL if it hits the overlay itself.
  • Layer 3 β€” last resort: if all fail, the drag is cancelled (the foreground window is deliberately never used, so dragging from empty taskbar space pins nothing).

Hover pre-sampling: while hovering, the resolver runs read-only every loop and caches g_hoverCandidate with a timestamp. At mouse-down, a fresh candidate is used directly, so the drag feels instant.


16. Drag & reorder state machines

The worker runs a drag FSM each iteration: DRAG_IDLE β†’ DRAG_PRESS β†’ {SmartLaunch | DRAG_REORDER | DRAG_DRAGGING} β†’ DRAG_DROPPED β†’ DRAG_IDLE, with DRAG_CANCELLED as the forced-reset path.

  • A quick release (within CLICK_MAX_MS, under CLICK_MAX_MOVE_PX) is a click β†’ SmartLaunch(idx) (focus if running, else ShellExecuteExW, rate-limited).
  • Travel past REORDER_THRESHOLD_PX over an icon β†’ DRAG_REORDER; UpdateReorderPositions() spreads the other icons around the gap, CommitReorder() does the std::rotate and saves.
  • Travel past DRAG_THRESHOLD_PX off an icon β†’ DRAG_DRAGGING (pin/unpin path, ghost preview + rope).
  • HardStateReset() is the safety net (called from WM_RBUTTONUP and unpin-all) β€” clears drag paths, indices, ghost, and forces DRAG_IDLE.

17. The drag rope (tether)

A separate layered window (g_tetherWnd / g_tetherDIB / g_tetherBits) draws the "balloon thread" between the icon's dock slot and the cursor during an unpin drag. It is purely decorative.

  • The moving tip is spring-smoothed (THREAD_SPRING = 0.42, frame-rate scaled) for a lively whip lag.
  • THREAD_MAX_STRETCH_PX (= dragRopeBreakLength, 150–650) is the max length. Past it the rope tears mid-thread (g_tetherBreaking, frozen anchor/tip) and fires the unpin + dust vanish.
  • Released before breaking with unpinTrigger = 0 β†’ the rope retracts (g_tetherRetracting) and the icon stays pinned. With unpinTrigger = 1, dropping anywhere off the dock also unpins.
  • Appearance: THREAD_THICKNESS (1–10) and hue (THREAD_HUE, default earthy tan). The rope is always a single earthy colour. The window is pre-warmed at init (PrewarmLayered) to avoid first-use lag.

18. The dust vanish effect

The "Thanos" disintegration (VANISH_MS = 900) is a self-contained particle system on its own layered window (g_vanishWnd / g_vanishDIB):

BeginVanish() β†’ AddIconVanish() (samples the icon into VanishParticles with drift velocities) β†’ CommitVanish() (derives accent colour, bounding box, clamps to 4096Β²) β†’ UpdateVanishWindow() advances one frame per tick and presents via UpdateLayeredWindow. One vanish can span many icons at once (used by unpin-all). It supports both the double-right-click unpin (requested from the UI thread via g_vanishReq*) and the mid-drag rope break.


19. Dynamic dock sizing & scrolling

The app region resizes to fit: never below MIN_APP_SLOTS (5), never above MAX_VISIBLE_APP_SLOTS (10). Beyond 10 pins the region becomes a fixed viewport; g_appScrollStart selects which contiguous window of ordinals is shown, and the mouse wheel pages it. g_scrollNavUntil / g_scrollNavPt protect a wheel-selected highlight from stray WM_MOUSEMOVE for SCROLL_NAV_LOCK_MS. Workspace pins (enableExplorerWorkspacePins, max MAX_WORKSPACE_PINS = 2) are left-anchored and always visible. g_dockWidthDirty triggers a re-fit when counts change.


20. Rendering, glass & rounded corners

WM_PAINT draws all icons into a persistent off-screen buffer (g_alphaBlendDC/g_alphaBlendBmp) then blits once. Per icon: position + hover scale, DrawIconEx at opacity*255, running dot, lifted-source dimming, drop-zone highlight, and the limit flash.

  • Rounded corners (cornerRoundness 0–100): DWM corner attribute (DWMWCP_DONOTROUND / ROUNDSMALL / ROUND) plus a continuous clip radius = (h * 0.5) * (roundness / 100), so it's smooth and live-updatable, never pixelated.
  • Workspace divider (showWorkspaceDivider): boolean toggle for the gold divider pill between workspace pins and app pins (the old right-edge separator line was removed).

21. Persistence

HKEY_CURRENT_USER\Software\WindhawkMods\taskbar-quick-pin
  Value: PinnedApps (REG_MULTI_SZ)  β€” one full exe path per entry, in dock order

SavePinnedApps() snapshots paths under g_cs, then writes outside the lock (after every pin/unpin/unpin-all/reorder). LoadPinnedApps() runs at init: validates each path exists, extracts the icon, appends to g_pinnedApps; missing paths are silently dropped. Positions are corrected later by ReseatIconPositions().


22. Multi-monitor docks

multiMonitorDock creates a mirrored, read-only secondary overlay per non-primary taskbar. Secondary docks share g_pinnedApps and are driven by the primary worker via RepaintSecondaryDocks() (guarded by their own lock). They update on WM_DISPLAYCHANGE. Drag-to-pin works on the primary only; this is Beta. (Note: the primary dock itself is composed of layered surfaces β€” the app overlay plus the rope/vanish overlays β€” which is why you may see more than one dock-owned window on the primary monitor.)


23. Safety guards & exclusions

  • IsSystemWindow rejects Explorer, SearchHost, ShellExperienceHost, StartMenuExperienceHost, LogonUI, and classes Progman / Shell_TrayWnd / WorkerW.
  • IsExcludedApp rejects RuntimeBroker, WerFault, CredentialUIBroker, ApplicationFrameHost (the hosted UWP app is used instead). explorer.exe is excluded unless enableExplorerWorkspacePins is on.
  • Icon quality guard rejects blank/hidden icons and the shell's generic placeholder silhouette.
  • Duplicate guard (IsPinned) and capacity guard (app-pin count vs the maxPinnedApps setting, i.e. min(MAX_APP_PINS, MAX_PINNED_APPS), with TriggerLimitFlash() on overflow).

24. Hooks, build flags & dependencies

No Win32 API hooks. The mod only uses RegisterHotKey, in-process IUIAutomation, GetAsyncKeyState polling, and SHAppBarMessage (auto-hide) β€” plus its own layered top-level windows. (There is no SetWinEventHook; taskbar geometry comes purely from the worker's polling FSM.) Because it runs as a tool mod in its own windhawk.exe process (not injected into explorer.exe), a crash only tears down that process β€” the shell is unaffected and the dock simply disappears. No trampoline risk.

@compilerOptions -lshell32 -lole32 -loleaut32 -luuid -lshlwapi
                 -lgdi32 -lmsimg32 -luiautomationcore -ldwmapi -lwinmm

-lwinmm is used to raise the system timer resolution to 1 ms so Sleep(8) is honoured for smooth animation. Targets x86_64-pc-windows-msvc, C++17, Windows 11.


25. Contributing

Contributions welcome β€” bug reports, docs, and features.

  • Issues: ramensoftware/windhawk-mods.
  • Pull requests: keep the single-file structure, respect the thread-safety rules in Β§12, and make sure GDI resources are created once and freed in Wh_ModUninit (in reverse order). Be extremely careful adding any new cross-thread shared state β€” route it through g_cs or interlocked globals like the vanish request path.
  • The codebase has zero external dependencies and runs as a tool mod in its own windhawk.exe process β€” it is not injected into explorer.exe. Avoid hooking Win32 functions.

v2.5.4

  • Broadcast-safe lock glow -- the lock/unlock glow window now lives on the dock's message-pumping UI thread, so a system-wide broadcast (theme change, WM_SETTINGCHANGE, some app launches) can no longer stall on it.
  • Correct placement on scaled / mixed-DPI displays -- the dock now sets its own per-monitor-v2 DPI awareness, so it lands in the right spot and stays crisp instead of being stretched.
  • "Separator opacity" is now "Show workspace divider" (showWorkspaceDivider) -- the old 0-100 value behaved the same for every value 1-100, so it is now a simple on/off toggle for the gold divider between workspace pins and app pins.

v2.5.3

  • πŸͺΆ Leaner tool-mod runtime. β€” General optimisation of the tool-mod process.
  • ✨ Drag-to-pin feedback layer. β€” A glow bloom shows green ("there's room") or red ("dock full") while you drag an app toward the dock.
  • πŸ–₯️ Cleaner fullscreen & Snipping Tool handling. β€” The dock hides smoothly under fullscreen apps and the Windows native Snipping Tool overlay, with anti-flicker so it reappears seamlessly.
  • 🎯 Refined feedback behaviour. β€” Dragging or deleting an already-pinned icon near the dock now stays calm in both pin-limit states (dock full or with room) β€” no false "dock full" flash for an app that is already pinned.
  • 🧱 New "Hide dock outline" toggle (hideDockBorder). β€” Turn off the thin grey Windows 11 outline drawn around the dock. Purely cosmetic; the dock, icons and rounded corners are unchanged.
  • 🎬 Two lock/unlock flash animations, with a toggle (enableLockAnimation). β€” Off: a brief highlight on the dock's real edge. On: a loading-style glow sweeps left β†’ right across the whole dock. Colours unchanged (gold when locking, green when unlocking).
  • πŸ”§ Some more stability & polish improvements.

v2.5.2

  • πŸ—οΈ Architectural change β€” the mod now @include windhawk.exe, running as a tool mod in its own dedicated process.
  • ⚑ Code optimised.

v2.5.1

  • ⚑ Code optimised & lower memory usage. β€” No behavioural change, just leaner and lighter.
  • πŸͺœ New 5-stage resolve pipeline to cut resource usage. App identity is now settled through five ordered stages.
    1. Cache hit β€” Reuse the last resolved identity for the window/point (no work).
    2. Fast window probe β€” Cheap Get*/class checks before any heavyweight call.
    3. UIAutomation resolve β€” The authoritative taskbar-surface lookup, only if 1–2 miss.
    4. Process fallback β€” Cursor-inside process match when UIA can't name the target.
    5. Miss / sentinel β€” Give up cleanly (no pin) instead of guessing wrong.
  • πŸ” Workspace pins re-open every time. β€” A Pinned workspace dock icon now resolves to the "Explorer workspace".
  • ⌨️ Bare-key P / U / L gestures now work when enabled. β€” These gestures act on the foreground window.
  • πŸͺŸ Focus-if-running targets a real window. β€” Improved
  • πŸ†” Collision-free workspace IDs. MakeWorkspaceId now uses CoCreateGuid

v2.5.0

  • 🧡 Dedicated UI thread architecture (g_uiThread): all overlay, ghost, tether, vanish, and dialog windows are registered, created, pumped, and destroyed on their dedicated thread.
  • πŸ›‘οΈ Safe mod teardown (Wh_ModUninit): joins worker and UI threads gracefully with g_exitEvent and unregisters all 7 custom window classes preventing crashes on reload.
  • βš™οΈ Unified settings loading via LoadSettings() and decoupled pinned app limits.
  • 🧹 Code hygiene & stability: eliminated memory leaks, dangling class registrations, and cross-thread race conditions.

v2.0.0

  • πŸͺ’ Drag rope (tether) with configurable thickness, break length, and colour; plus an unpin trigger choice (only-on-break vs break-or-drop-outside).
  • πŸ’¨ Dust ("Thanos") disintegration effect on unpin.
  • πŸ”’ Lock the dock with triple-tap L, including an interactive lock-glow flash; gesture-unpins are refused while locked.
  • ⌨️ Triple-tap P / U to pin / unpin the focused app.
  • πŸ–±οΈ Scroll-wheel navigation across pins with macOS-style magnify.
  • πŸ“ Dynamic dock sizing β€” shrinks to a 5-slot minimum, grows to a 10-slot cap, then scrolls.
  • πŸͺŸ Live corner roundness (0–100) via DWM, and richer glass feedback.
  • πŸ—‚οΈ Explorer workspace pins (opt-in), dock gap from Start, and a logging level setting.
  • πŸ–₯️ Multi-monitor mirrored read-only docks (Beta).

v1.0.0

  • Initial release of Taskbar Quick Pin Dock.

License

This project is licensed under the MIT License.


Created with ❀️ by Ashix · GitHub · X

Thanks to the Taskbar Dock Animation and Taskbar Dock Animation Plus mods for animation refinements.

About

Native-style Windows taskbar quick pin dock for Windhawk with drag-to-pin, drag-to-unpin.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages