Add taskbar clock to left - #5189
Conversation
Add Taskbar Left Performance Clock based on m417z's Taskbar Clock Customization.
Moves the native Windows 11 clock to the left without shifting centered taskbar apps.
|
Thanks for the pull request! This repository uses a two-stage review: an AI review that you run yourself, followed by a human review. To get started, comment See the pull request review process for the full details. |
|
/ai-review |
Submission reviewNote: This review was done by Claude. Due to the amount of submissions, doing a fully manual review for each pull request is no longer feasible. Thank you for understanding. Remember: The AI reviewer can be wrong - it may misread code, flag correct code as broken, or suggest changes that make things worse. Treat its findings as suggestions to verify, not instructions to follow blindly. You're responsible for the code you submit, so if a finding doesn't hold up, say so instead of changing working code to satisfy it. Please address the following issues. The items in the collapsed sections are optional, so it's your call whether to address them. The overall approach is sound — hooking 1. Global containers hold strong XAML/WinRT references and are destroyed at process shutdown
Both need the [[clang::no_destroy]] std::optional<std::vector<DeferredClockData>>
g_deferredClocks{std::in_place};
[[clang::no_destroy]] std::optional<std::vector<MovedClockData>>
g_movedClocks{std::in_place};Use 2.
Concurrent Worse, The fix is to stop touching 3. Teardown can hang, spin at 100% CPU, or silently leave a mod-owned delegate registered The unload path is built entirely on
Replacing the async dispatch + polling with a synchronous 4.
5. The left host overlays the leftmost taskbar elements and steals their clicks
The mod needs to either reserve real space at the left (e.g. shift 6. Add a screenshot to the README This is a purely visual mod and the README has no image. Please add a screenshot (or GIF) showing the clock on the left — only Optional improvements
Minor polish — none of this affects users, so it's your call.
Functionality notes
Non-critical observations and ideas about the feature behavior itself.
Next steps:
See the review process for details. |
|
/ai-review |
Submission reviewNote: This review was done by Claude. Due to the amount of submissions, doing a fully manual review for each pull request is no longer feasible. Thank you for understanding. Remember: The AI reviewer can be wrong - it may misread code, flag correct code as broken, or suggest changes that make things worse. Treat its findings as suggestions to verify, not instructions to follow blindly. You're responsible for the code you submit, so if a finding doesn't hold up, say so instead of changing working code to satisfy it. Please address the following issues. The items in the collapsed sections are optional, so it's your call whether to address them. Overall the mod is in good shape: the scope is narrow ( 1. A failed teardown leaves live XAML delegates pointing into the unloaded mod image (crash).
There's a second, narrower problem with the timeout: Please use the canonical implementation with a plain 2. Failed symbol hooking is retried on every
Mark the module as attempted rather than as succeeded, the way taskbar-clock-customization.wh.cpp#L5319-L5330 does it: if (!g_systemTrayHooked.exchange(true)) {
if (HookSystemTray(systemTrayModule)) { ... }
}While you're there, please add an early-out at the top of 3.
4.
(Note that in that scenario the feature wouldn't work anyway: Either resolve it one way — the clock and the taskbar root Grid must be in the same visual tree for 5. Taskbar alignment changes at runtime aren't handled.
6. Add a screenshot to the README. The mod's effect is purely visual, so a before/after screenshot (or GIF) would help a lot. Only Optional improvements
Minor polish — none of this affects users, so it's your call.
Functionality notes
Non-critical observations and ideas about the feature behavior itself.
Next steps:
See the review process for details. |
|
/ai-review |
Submission reviewNote: This review was done by Claude. Due to the amount of submissions, doing a fully manual review for each pull request is no longer feasible. Thank you for understanding. Remember: The AI reviewer can be wrong - it may misread code, flag correct code as broken, or suggest changes that make things worse. Treat its findings as suggestions to verify, not instructions to follow blindly. You're responsible for the code you submit, so if a finding doesn't hold up, say so instead of changing working code to satisfy it. Please address the following issues. The items in the collapsed sections are optional, so it's your call whether to address them. Nice submission overall — the symbol strings, the module-version split at 1.
// On current Windows builds, SystemTray_Main can be owned by a different
// thread than Shell_TrayWnd. Remember the actual XAML owner thread from the
// clock callback and use it for teardown and settings changes.
g_clockThreadId = GetCurrentThreadId();If that's true, mutating a Either serialize the container access, or publish just the value the extent hook needs (e.g. an atomic 2. The relocation runs inside a The originalParent.InvalidateMeasure();
systemTrayFrame.InvalidateMeasure();
root.InvalidateMeasure();
root.UpdateLayout();
Defer the move off the layout pass instead, e.g. // Runs one of the margin updaters on the taskbar thread, deferred off the
// current layout pass (changing margins during arrange would re-enter layout).
void ScheduleOnTaskbarThread(FrameworkElement element,
void (*func)(FrameworkElement)) {
element.Dispatcher().TryRunAsync(
winrt::Windows::UI::Core::CoreDispatcherPriority::High,
[element, func]() { func(element); });
}3. The
4. Give up less easily when delivering the teardown callback
if (windows->preferredThreadId &&
threadId == windows->preferredThreadId &&
!windows->preferredThreadWindow) {
windows->preferredThreadWindow = window;
}If that window is destroyed between 5. The single The mod has exactly one setting, and turning it off makes the mod do nothing — which is what disabling the mod in Windhawk already does. Dropping it removes Optional improvements
Minor polish — none of this affects users, so it's your call.
Functionality notes
Non-critical observations and ideas about the feature behavior itself.
Next steps:
See the review process for details. |
Restore the clock to its native right-side position when taskbar apps are left-aligned, and move it back to the left when centered alignment is restored. This prevents overlap without shifting application icons.
|
/ai-review |
Submission reviewNote: This review was done by Claude. Due to the amount of submissions, doing a fully manual review for each pull request is no longer feasible. Thank you for understanding. Remember: The AI reviewer can be wrong - it may misread code, flag correct code as broken, or suggest changes that make things worse. Treat its findings as suggestions to verify, not instructions to follow blindly. You're responsible for the code you submit, so if a finding doesn't hold up, say so instead of changing working code to satisfy it. Please address the following issues. The items in the collapsed sections are optional, so it's your call whether to address them. Overall the mod is in good shape: the 1. The deferred alignment-update machinery (
2.
The canonical pattern gates on identity with the newly loaded module — see taskbar-icon-size.wh.cpp#L2446: if (!g_systemTrayModuleHooked && GetSystemTrayModuleHandle() == module &&
module != GetTaskbarViewModuleHandle() &&
!g_systemTrayModuleHooked.exchange(true)) { ... }That way a role is only ever attempted against a module that actually just loaded, and a wrong fallback can't consume the one attempt. Optional improvements
Minor polish — none of this affects users, so it's your call.
Functionality notes
Non-critical observations and ideas about the feature behavior itself.
Next steps:
See the review process for details. |
Revert the unreliable deferred-message hook changes and restore the previously tested implementation.
|
/ai-review |
|
This pull request has already had 3 AI reviews in the last 24 hours, which is the limit, so no review was posted this time. Comment |
|
/ai-review |
Submission reviewNote: This review was done by Claude. Due to the amount of submissions, doing a fully manual review for each pull request is no longer feasible. Thank you for understanding. Remember: The AI reviewer can be wrong - it may misread code, flag correct code as broken, or suggest changes that make things worse. Treat its findings as suggestions to verify, not instructions to follow blindly. You're responsible for the code you submit, so if a finding doesn't hold up, say so instead of changing working code to satisfy it. Please address the following issues. The items in the collapsed sections are optional, so it's your call whether to address them. Overall this is a careful implementation — the module resolution mirrors 1.
void WINAPI TaskbarFrame_SystemTrayExtent_Hook(void* pThis, double value) {
double layoutReservedWidth = GetLayoutReservedClockWidthForTaskbarFrame(pThis);
TaskbarFrame_SystemTrayExtent_Original(pThis, value + layoutReservedWidth);
int centeredAlignment = TaskbarUsesCenteredAlignment() ? 1 : 0;
int previousAlignment = g_lastTaskbarCenteredAlignment.exchange(centeredAlignment);
if (previousAlignment >= 0 && previousAlignment != centeredAlignment) {
...
QueueKnownClockPlacementUpdate(); // <-- runs on whatever thread TaskbarFrame is on
}
2. Two entry points can let a C++ exception escape into system code. Every other entry point wraps its work in
Wrap both in the same 3. Teardown is best-effort and silently gives up, leaving mod-owned delegates registered after the DLL is unloaded.
Concretely: instead of filtering the Optional improvements
Minor polish — none of this affects users, so it's your call.
Functionality notes
Non-critical observations and ideas about the feature behavior itself.
Next steps:
See the review process for details. |
|
/ready-for-reviewer |
|
I reviewed the remaining AI findings. I restored this revision because a later attempt to address them introduced a confirmed regression involving This restored revision passed compilation and runtime testing, including enable/disable, Explorer restart, taskbar alignment changes, and compatibility testing with clock customization mods. The remaining threading, exception-boundary, and teardown concerns are acknowledged. I would prefer human reviewer guidance before making further speculative lifecycle changes that could introduce regressions. |
|
From the code: // On current Windows builds, SystemTray_Main can be owned by a different
// thread than Shell_TrayWnd.I don't think it's ever correct. If it's a mistake, update the comment and adjust the code. It will likely also resolve the first review note. Address this:
Also, I tested the mod on the latest Windows 11 build (26200.9278) and it didn't work. Please make sure it works on that version, which is going to be released for everyone in 10 days. |
|
/ai-review |
Submission reviewNote: This review was done by Claude. Due to the amount of submissions, doing a fully manual review for each pull request is no longer feasible. Thank you for understanding. Remember: The AI reviewer can be wrong - it may misread code, flag correct code as broken, or suggest changes that make things worse. Treat its findings as suggestions to verify, not instructions to follow blindly. You're responsible for the code you submit, so if a finding doesn't hold up, say so instead of changing working code to satisfy it. Please address the following issues. The items in the collapsed sections are optional, so it's your call whether to address them. Overall the structure is solid: the module discovery ( 1. The left-host offset is computed once and never refreshed, so the clock drifts out of place
data.leftHost.Margin(Thickness{GetLeftHostOffset(root), 0, 0, 0});The Widgets/weather entry point is not a fixed-width button — its width changes as the weather text updates (temperature/condition strings differ in length), and it can be shown or hidden at runtime (Settings → Personalization → Taskbar → Widgets). Every one of those changes leaves the clock either overlapping the widgets button or floating with a growing gap after it, until the mod happens to relocate the clock again. There is also a startup ordering case: Keep the position live instead of snapshotting it: hold on to the widgets 2. The "taskbar alignment changed" trigger isn't guaranteed to fire The only place the mod notices that the user switched between centered and left-aligned taskbar is inside the layout hook: void WINAPI TaskbarFrame_SystemTrayExtent_Hook(void* pThis, double value) {
...
int centeredAlignment = TaskbarUsesCenteredAlignment() ? 1 : 0;
int previousAlignment = g_lastTaskbarCenteredAlignment.exchange(centeredAlignment);
if (previousAlignment >= 0 && previousAlignment != centeredAlignment) {
...
QueueKnownClockPlacementUpdate();
}
A deterministic trigger would be better than piggybacking on a layout setter. Two options:
Related: 3. If the taskbar-thread cleanup can't run, the mod unloads with live delegates in it Both teardown paths funnel through auto taskbarWindows = FindExplorerTaskbarWindows();
if (taskbarWindows.empty()) {
Wh_Log(L"%s skipped: taskbar window not found", operation);
return false;
}
Add a fallback that doesn't depend on finding an if (auto dispatcher = content.Dispatcher(); dispatcher && !dispatcher.HasThreadAccess()) {
dispatcher.RunAsync(winrt::Windows::UI::Core::CoreDispatcherPriority::High,
[] { /* revoke handlers, restore clocks */ }).get();
}Optional improvements
Minor polish — none of this affects users, so it's your call.
Functionality notes
Non-critical observations and ideas about the feature behavior itself.
Next steps:
See the review process for details. |
Adds a new Windows 11 mod that moves the native clock and notification-center button to the left side of the taskbar.
The mod is designed to:
Credits:
Taskbar-related implementation techniques were informed by existing Windhawk mods by Michael Maltsev (@m417z), particularly Taskbar Clock Customization and Multirow Taskbar. Development and code review were assisted by OpenAI Codex.
Changelog
Not applicable. This pull request introduces a new mod.
Mod authorship
If this pull request introduces a new mod, please complete the section below.
This mod was created by:
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.