terminal/src/cascadia/TerminalApp/TaskbarState.cpp
Mike Griese a14b6f89f6
Combine progress states in the tab, taskbar (#10755)
## Summary of the Pull Request
![background-progress-000](https://user-images.githubusercontent.com/18356694/126653006-3ad2fdae-67ae-4cdb-aa46-25d09217e365.gif)

This PR causes the Terminal to combine taskbar states at the tab and window level, according to the [MSDN docs for `SetProgressState`](https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-itaskbarlist3-setprogressstate#how-the-taskbar-button-chooses-the-progress-indicator-for-a-group). 

This allows the Terminal's taskbar icon to continue showing progress information, even if you're in a pane/tab that _doesn't_ have progress state. This is helpful for cases where the user may be running a build in one tab, and working on something else in another.

## References

* [`SetProgressState`](https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-itaskbarlist3-setprogressstate#how-the-taskbar-button-chooses-the-progress-indicator-for-a-group)
* Progress mega: #6700 

## PR Checklist
* [x] Closes #10090
* [x] I work here
* [ ] Tests added/passed
* [n/a] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

This also fixes a related bug where transitioning from the "error" or "warning" state directly to the "indeterminate" state would cause the taskbar icon to get stuck in a bad state.

## Validation Steps Performed

<details>
<summary><code>progress.cmd</code></summary>

```cmd
@echo off
setlocal enabledelayedexpansion

set _type=3
if (%1) == () (
    set _type=3
) else (
    set _type=%1
)



if (%_type%) == (0) (
    <NUL set /p =]9;4
    echo Cleared progress
)
if (%_type%) == (1) (
    <NUL set /p =]9;4;1;25
    echo Started progress (normal, 25^)
)
if (%_type%) == (2) (
    <NUL set /p =]9;4;2;50
    echo Started progress (error, 50^)
)
if (%_type%) == (3) (
    @rem start indeterminate progress in the taskbar
    @rem this `<NUL set /p =` magic will output the text _without a newline_

    <NUL set /p =]9;4;3
    echo Started progress (indeterminate, {omitted})
)
if (%_type%) == (4) (
    <NUL set /p =]9;4;4;75
    echo Started progress (warning, 75^)
)

```

</details>
2021-08-10 11:16:17 +00:00

46 lines
1.4 KiB
C++

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "TaskbarState.h"
#include "TaskbarState.g.cpp"
namespace winrt::TerminalApp::implementation
{
// Default to unset, 0%.
TaskbarState::TaskbarState() :
TaskbarState(0, 0){};
TaskbarState::TaskbarState(const uint64_t dispatchTypesState, const uint64_t progressParam) :
_State{ dispatchTypesState },
_Progress{ progressParam } {}
uint64_t TaskbarState::Priority() const
{
// This seemingly nonsensical ordering is from
// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-itaskbarlist3-setprogressstate#how-the-taskbar-button-chooses-the-progress-indicator-for-a-group
switch (_State)
{
case 0: // Clear = 0,
return 5;
case 1: // Set = 1,
return 3;
case 2: // Error = 2,
return 1;
case 3: // Indeterminate = 3,
return 4;
case 4: // Paused = 4
return 2;
}
// Here, return 6, to definitely be greater than all the other valid values.
// This should never really happen.
return 6;
}
int TaskbarState::ComparePriority(const winrt::TerminalApp::TaskbarState& lhs, const winrt::TerminalApp::TaskbarState& rhs)
{
return lhs.Priority() < rhs.Priority();
}
}