PowerDisplay: Draw the tray icon's hover UI instead of the Shell tooltip - #49555
Closed
moooyo wants to merge 1 commit into
Closed
PowerDisplay: Draw the tray icon's hover UI instead of the Shell tooltip#49555moooyo wants to merge 1 commit into
moooyo wants to merge 1 commit into
Conversation
Moves the notification-area icon onto NOTIFYICON_VERSION_4 and gives it its own hover presentation, so a caller can attach a transient readout to the icon - something the standard Shell tooltip cannot do, because it cannot be shown on demand. Registration and recovery. Nothing polls a healthy registration. A lost icon is reported by the TaskbarCreated broadcast, by a failing Shell_NotifyIconGetRect on the next hover, or by the settings-update path, and each schedules a check through TrayIconRegistrationBackoff (250 ms to 5 s, capped) that keeps retrying while NIM_ADD fails. The health check uses Shell_NotifyIconGetRect, which also succeeds for an icon parked in the notification overflow, so a hidden icon is not mistaken for a lost one. NOTIFYICON_VERSION_4. The callback packing differs between versions - the id moves to the high word of lParam, the event to the low word, and the Shell supplies an anchor point in wParam - so DispatchTrayNotification decodes according to whether NIM_SETVERSION actually succeeded. Version 4 adds NIN_SELECT, NIN_KEYSELECT and WM_CONTEXTMENU while still forwarding the raw button messages, so the legacy cases are suppressed while it is active; handling both would open the context menu twice. Hover UI. NIF_TIP without NIF_SHOWTIP stops the Shell drawing its tooltip and lets TrayWheelFeedbackWindow present instead: a no-activate, click-through TransparentWindow showing the app name after a 500 ms hover, and whatever UpdateAdjustmentFeedback is given for two seconds after that. Formatting that text is deliberately the caller's job, so wording and its localized resources stay with whatever gesture produced them rather than leaking into the tray plumbing. Two consequences of replacing the tooltip are deliberate, and are called out in the module design doc and in EnsureTrayIconIdentity: - The overlay is created lazily on first hover and kept for the process lifetime, so the icon costs a XAML window and a 250 ms hover watchdog it did not cost before. - A hover that never involves the cursor - keyboard or touch focus in the notification area - shows no text at all, because the overlay is only presented when GetCursorPos lands inside the icon rectangle. szTip is still supplied, so the UI Automation name and the overflow flyout label are unaffected, but there is no visible hover text for those input methods. Placement, hover timing, rectangle arithmetic and the backoff sequence are pure logic in PowerDisplay.Lib with unit tests. The Win32 and WinUI glue is not unit tested.
Contributor
Author
|
Closed due to no enough motivation to push this impl for a very tiny feature. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary of the Pull Request
Carved out of #49446 so the tray-icon plumbing can be reviewed on its own, ahead of the mouse-wheel feature that motivated it.
This moves the PowerDisplay notification-area icon onto
NOTIFYICON_VERSION_4and gives it its own hover presentation, replacing the standard Shell tooltip. The reason for doing that at all is that the Shell tooltip cannot be shown on demand — so a feature that wants to attach a transient readout to the icon (in #49446: the brightness percentage as you scroll) has nowhere to put it.UpdateAdjustmentFeedback(string?)is the seam #49446 then builds on. Formatting the text is deliberately the caller's job, so wording and its localized resources stay with whatever gesture produced them rather than leaking into the tray plumbing.Dependency direction: #49446 will be rebased onto this branch. Nothing here depends on #49446.
PR Checklist
Communication is unchecked on purpose — see Open question below. No new binaries or projects: everything lands in existing assemblies.
Detailed Description of the Pull Request / Additional comments
Registration and recovery. Nothing polls a healthy registration. A lost icon is reported by the
TaskbarCreatedbroadcast, by a failingShell_NotifyIconGetRecton the next hover, or by the settings-update path, and each schedules a check throughTrayIconRegistrationBackoff(250 ms → 5 s, capped) that keeps retrying whileNIM_ADDfails. The health check usesShell_NotifyIconGetRect, which also succeeds for an icon parked in the notification overflow, so a hidden icon is not mistaken for a lost one.NOTIFYICON_VERSION_4. The callback packing differs between versions — the id moves to
HIWORD(lParam), the event toLOWORD(lParam), and the Shell supplies an anchor point inwParam— soDispatchTrayNotificationdecodes according to whetherNIM_SETVERSIONactually succeeded, and the legacy path is kept working. Version 4 addsNIN_SELECT,NIN_KEYSELECTandWM_CONTEXTMENUwhile still forwarding the raw button messages, so the legacy cases are suppressed while it is active; handling both would open the context menu twice and toggle the window twice.Hover UI.
NIF_TIPwithoutNIF_SHOWTIPstops the Shell drawing its tooltip and letsTrayWheelFeedbackWindowpresent instead — a no-activate (WS_EX_NOACTIVATE), click-through (WS_EX_TRANSPARENT+HTTRANSPARENT)TransparentWindow.UpdateAdjustmentFeedback(text)Open question for reviewers
Replacing the Shell tooltip has two consequences that are deliberate, documented in
design.mdand inEnsureTrayIconIdentity, and that I think need a maintainer's call before this ships:GetCursorPoslands inside the icon rectangle, so focusing the icon from the keyboard shows nothing.szTipis still supplied, so the UI Automation name and the overflow-flyout label are unaffected — but there is no visible hover text for those input methods. This is a real capability regression, not an implementation gap.An alternative considered and rejected: keep
NIF_SHOWTIPand only use the overlay for the transient readout. That preserves the native tooltip for all input methods, but means two hover presentations to maintain and keep from diverging.Also worth a reviewer opinion: the
TrayWheelFeedback*type names come from the motivating consumer in #49446. Happy to rename them toTrayHoverFeedback*if preferred.Validation Steps Performed
PowerDisplay, x64 Debug — clean, no warnings.PowerDisplay.Lib.UnitTests219 passed. Placement, hover timing, rectangle arithmetic and the backoff sequence are pure logic inPowerDisplay.Liband are covered there, including negative-origin secondary monitors, the notification overflow, taskbar-edge selection, and work-area clamping.TrayIconServiceandTrayWheelFeedbackWindowis not unit tested.Not yet verified on hardware, and called out so a reviewer can weigh it:
NIN_POPUPOPENon keyboard focus. If it does, the overlay could be anchored to the icon rectangle without the cursor check, which would close consequence (1) above while keeping a single presentation.