Squashed commit of the following:

commit 73e379238b
Author: leileizhang <leilzh@microsoft.com>
Date:   Tue Dec 9 10:13:48 2025 +0800

    Add FancyZones CLI for command-line layout management (#44078)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request
    Adds a new command-line interface (CLI) tool for FancyZones, enabling
    users and automation scripts to manage window layouts without the GUI.

    **Commands:**
    | Command | Aliases | Description |
    |---------|---------|-------------|
    | `help` | | Displays general help information for all commands |
    | `open-editor` | `editor`, `e` | Launch FancyZones layout editor |
    | `get-monitors` | `monitors`, `m` | List all monitors and their
    properties |
    | `get-layouts` | `layouts`, `ls` | List all available layouts with
    ASCII art preview |
    | `get-active-layout` | `active`, `a` | Show currently active layout |
    | `set-layout <uuid>` | `set`, `s` | Apply layout by UUID or template
    name |
    | `open-settings` | `settings` | Open FancyZones settings page |
    | `get-hotkeys` | `hotkeys`, `hk` | List all layout hotkeys |
    | `set-hotkey <key> <uuid>` | `shk` | Assign hotkey (0-9) to custom
    layout |
    | `remove-hotkey <key>` | `rhk` | Remove hotkey assignment |

    **Key Capabilities:**
    - ASCII art visualization of layouts (grid, focus, priority-grid,
    canvas)
    - Support for both template layouts and custom layouts
    - Monitor-specific layout targeting (`--monitor N` or `--all`)
    - Real-time notification to FancyZones via Windows messages
    - Native AOT compilation support for fast startup

    ### Example Usage

    ```bash
    # List all layouts with visual previews
    FancyZonesCLI.exe ls

    # Apply "columns" template to all monitors
    FancyZonesCLI.exe s columns --all

    # Set custom layout on monitor 2
    FancyZonesCLI.exe s {uuid} --monitor 2

    # Assign hotkey Win+Ctrl+Alt+3 to a layout
    FancyZonesCLI.exe shk 3 {uuid}
    ```

    https://github.com/user-attachments/assets/2b141399-a4ca-4f64-8750-f123b7e0fea7

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 4710b816b4
Author: Dave Rayment <dave.rayment@gmail.com>
Date:   Mon Dec 8 21:01:56 2025 +0000

    [CmdPal] Optimise MainListPage's results display by merging already-sorted lists (#44126)

    ## Summary of the Pull Request
    This PR replaces the current LINQ-based results compilation query of
    combining, sorting and filtering the four result sources with a 3-way
    merge operation plus a final append. It provides a performance increase
    as well as a significant reduction in allocations.

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [x] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments
    The existing code:
    1. Limits the number of apps returned to a pre-defined maximum.
    2. Sorts the apps list.
    3. Appends filtered items, scored fallback items and the apps list
    together.
    4. Sorts the three lists based on their score.
    5. Appends the non-scored fallback items, with empty items excluded.
    6. Selects just the `Item` from each.
    7. Creates an array from the enumerable.

    ```csharp
        if (_filteredApps?.Count > 0)
        {
            limitedApps = _filteredApps.OrderByDescending(s => s.Score).Take(_appResultLimit).ToList();
        }

        var items = Enumerable.Empty<Scored<IListItem>>()
                              .Concat(_filteredItems is not null ? _filteredItems : [])
                              .Concat(_scoredFallbackItems is not null ? _scoredFallbackItems : [])
                              .Concat(limitedApps)
                              .OrderByDescending(o => o.Score)

                              // Add fallback items post-sort so they are always at the end of the list
                              // and eventually ordered based on user preference
                              .Concat(_fallbackItems is not null ? _fallbackItems.Where(w => !string.IsNullOrEmpty(w.Item.Title)) : [])
                              .Select(s => s.Item)
                              .ToArray();
    ```

    We can exploit the fact that each of the three 'scored' lists are
    pre-ordered, and replace the query with a 3-way merge and final append
    of the non-scored fallback items.

    By pre-sizing the results array we can avoid all the extra allocations
    of the LINQ-based solution.

    ### Proof of pre-ordering
    In `UpdateSearchText`, each of the lists is defined by calling
    `ListHelpers.FilterListWithScores`:

    ```csharp
        // Produce a list of everything that matches the current filter.
        _filteredItems = [.. ListHelpers.FilterListWithScores<IListItem>(newFilteredItems ?? [], SearchText, scoreItem)];
    ```

    ```csharp
        _scoredFallbackItems = ListHelpers.FilterListWithScores<IListItem>(newFallbacksForScoring ?? [], SearchText, scoreItem);
    ```

    ```csharp
        var scoredApps = ListHelpers.FilterListWithScores<IListItem>(newApps, SearchText, scoreItem);

    ...

        _filteredApps = [.. scoredApps];
    ```

    In `FilterListWithScores`, the results are ordered by score:

    ```csharp
       var scores = items
            .Select(li => new Scored<T>() { Item = li, Score = scoreFunction(query, li) })
            .Where(score => score.Score > 0)
            .OrderByDescending(score => score.Score);
    ```

    (This also makes the existing `OrderByDescending()` for `_filteredApps`
    before the LINQ query redundant.)

    ### K-way merge
    Since the results are pre-sorted, we can do a direct merge in linear
    time. This is what the new `MainListPageResultFactory`'s `Create`
    achieves. As the lists may be different sizes, the routine does a 3-way
    merge, followed by a 2-way merge and a single list drain to finish. Each
    element is only visited once.

    ### Benchmarks
    A separate benchmark project is
    [here](https://github.com/daverayment/MainListBench), written with
    Benchmark.net.

    The project compares the current LINQ-based solution against:
    1. An Array-based algorithm which pre-assigns a results array and still
    sorts the 3 scored sets of results. This shows a naive non-LINQ solution
    which is still _O(n log n)_ because of the sort.
    2. The k-way merge, which is described above. _O(n)_ for both time and
    space complexity.
    3. A heap merge algorithm, which uses a priority queue instead of
    tracking each of the lists separately. (This is _O(n log k)_ in terms of
    time complexity and _O(n + k)_ for space.)

    Care is taken to ensure stable sorting of items. When preparing the
    benchmark data, items with identical scores are assigned to confirm each
    algorithm performs identically to the LINQ `OrderBy` approach, which
    performs a stable sort.

    Results show that the merge performs best in terms of both runtime
    performance and allocations, sometimes by a significant margin. Compared
    to the LINQ approach, merge runs 400%+ faster and with at most ~20% of
    the allocations:

    <img width="1135" height="556" alt="image"
    src="https://github.com/user-attachments/assets/9f9d3932-1592-49d6-8a07-4ea3ba7a0cc5"
    />

    <img width="1149" height="553" alt="image"
    src="https://github.com/user-attachments/assets/ae9e9e0a-b255-4c1a-af4b-e791dea80fa4"
    />

    See here for all charts and raw stats from the run:
    https://docs.google.com/spreadsheets/d/1y2mmWe8dfpbLxF_eqPbEGvaItmqp6HLfSp-rw99hzWg/edit?usp=sharing

    ### Cons

    1. Existing performance is not currently an issue. This could be seen as
    a premature optimisation.
    2. The new code introduces an inherent contract between the results
    compilation routine and the lists, i.e. that they must be sorted.

    This PR was really for research and learning more about CmdPal (and a
    bit of algorithm practice because it's Advent of Code time), so please
    feel free to reject if you feel the cons outweigh the pros.

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed
    - Added unit tests to exercise the new code, which confirm that the
    specific ordering is preserved, and the filtering and pre-trimming of
    the apps list is performed as before.
    - Existing non-UI unit tests run. NB: I _could not_ run any UI Tests on
    my system and just got an early bail-out each time.
    - Manual testing in (non-AOT) Release mode.

commit b8a0163419
Author: Sam Rueby <samrueby@gmail.com>
Date:   Mon Dec 8 13:13:33 2025 -0500

    CmdPal: Arrow keys move logical grid pages (#43870)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [X] Closes: #41939
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [X] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed
    Before

    ![Before](https://github.com/user-attachments/assets/49853e8d-9113-425c-8230-e49fb9b8d640)

    After

    ![After](https://github.com/user-attachments/assets/a4597fe6-6503-4502-99cf-350425f5ef51)

    I noticed the double "active" line around the items when the ListPage is
    focused. I was unable to find where that is defined. Ideally, the
    black-border would go away.

    I tested with AOT turned on.

    The behavior accounts for suggestions. If the SearchBar is focused and
    there is a suggestion, right-arrow will [continue] to complete the
    suggestion.

commit 06fcbdac40
Author: Gordon Lam <73506701+yeelam-gordon@users.noreply.github.com>
Date:   Mon Dec 8 18:52:33 2025 +0800

    Update WinAppSDK to 1.8.3 (#44146)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request
    This pull request updates several dependencies to newer versions in the
    `Directory.Packages.props` file. The main focus is on upgrading the
    Microsoft Windows App SDK packages to ensure the project uses the latest
    features and bug fixes.

    Dependency version updates:

    * Upgraded `Microsoft.WindowsAppSDK`,
    `Microsoft.WindowsAppSDK.Foundation`, `Microsoft.WindowsAppSDK.AI`, and
    `Microsoft.WindowsAppSDK.Runtime` to their latest respective versions,
    replacing previous 1.8.25* releases with newer builds.
    <!-- Please review the items on the PR checklist before submitting-->

commit d515c67def
Author: leileizhang <leilzh@microsoft.com>
Date:   Mon Dec 8 13:34:33 2025 +0800

    Improve install scope detection to prevent mixed user/machine installations (#43931)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request
    The old implementation checked
    `HKLM\Software\Classes\powertoys\InstallScope` first. If this key
    existed (even as a remnant from incomplete uninstall), it would
    immediately return `PerMachine` without validating the actual
    installation.

    ### Fix
    - Uses Windows standard Uninstall registry (most reliable source of
    truth)
    - Identifies PowerToys Bundle by exact `BundleUpgradeCode` GUID match
    - MSI component entries (always in HKLM) are automatically ignored since
    they don't have `BundleUpgradeCode`
    - Checks HKCU first, then HKLM, properly handling the fact that Bundle
    location reflects true install scope

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes: #43696
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 9439b6df41
Author: Noraa Junker <noraa.junker@outlook.com>
Date:   Mon Dec 8 04:55:51 2025 +0100

    [Settings] Create a global static instance of SettingsUtils (#44064)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request

    SettingsUtils is initialized multiple times over the whole solution.
    This creates one singeltone instance (with the default settings), so it
    only has to be initialized once (and improve performance a bit with
    that)

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit a37add8f08
Author: 舰队的偶像-岛风酱! <frg2089@outlook.com>
Date:   Mon Dec 8 11:14:00 2025 +0800

    feat(cmdpal): add pinyin support for Chinese input method (#39354)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request

    - Add ToolGood.Words.Pinyin package to support pinyin conversion
    - Implement pinyin matching in StringMatcher class
    - Update project dependencies and Directory.Packages.props

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] **Closes:** #38417 #39343
    - [ ] **Communication:** I've discussed this with core contributors
    already. If work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end user facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    I've completed a rough implementation of pinyin support, but since I'm
    currently unsure where to add the toggle for pinyin support, this
    feature is enabled by default for now.

    https://github.com/user-attachments/assets/59df0180-05ad-4b4a-a858-29aa15e40fd2

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

    ---------

    Signed-off-by: 舰队的偶像-岛风酱! <frg2089@outlook.com>
    Co-authored-by: Yu Leng <yuleng@microsoft.com>

commit 60deec6815
Author: Gordon Lam <73506701+yeelam-gordon@users.noreply.github.com>
Date:   Mon Dec 8 09:52:55 2025 +0800

    Using centralized package management for vcxproj (#43920)

    ## Summary of the Pull Request
    This pull request updates the build system for several native and
    managed projects, modernizing NuGet package management and improving
    code analysis configuration. The main changes involve switching from
    legacy `packages.config` and manual `.props`/`.targets` imports to
    PackageReference style for native projects, updating package versions,
    and streamlining code analysis settings.

    **Build system modernization and package management:**

    * Migrated native projects (`PowerToys.MeasureToolCore.vcxproj`,
    `FindMyMouse.vcxproj`) from legacy `packages.config` and manual
    `.props`/`.targets` imports to NuGet PackageReference style, simplifying
    dependency management and build configuration. This includes removing
    the `packages.config` file and related import/error logic, and
    introducing `PackageReference` items for required packages.
    [[1]](diffhunk://#diff-76320b3a74a9241df46edb536ba0f817d7150ddf76bb0fe677e2b276f8bae95aL3-R18)
    [[2]](diffhunk://#diff-76320b3a74a9241df46edb536ba0f817d7150ddf76bb0fe677e2b276f8bae95aR41-L41)
    [[3]](diffhunk://#diff-76320b3a74a9241df46edb536ba0f817d7150ddf76bb0fe677e2b276f8bae95aL145-R153)
    [[4]](diffhunk://#diff-d3a7d80ebbca915b42727633451e769ed2306b418ef3d82b3b04fd5f79560f17L1-L17)
    [[5]](diffhunk://#diff-0f27869c4e90c8fd2c81f5688c58da99afcc9e5767e69ef7938265dbb6928e0fL3-R13)
    * Updated the centralized package versions in
    `Directory.Packages.props`, adding new entries for `boost`,
    `boost_regex-vc143`, `Microsoft.Windows.ImplementationLibrary`, and
    `Microsoft.WindowsAppSDK.Foundation` to support the new build system and
    dependencies.
    [[1]](diffhunk://#diff-5baf5f9e448ad54ab25a091adee0da05d4d228481c9200518fcb1b53a65d4156R10-R11)
    [[2]](diffhunk://#diff-5baf5f9e448ad54ab25a091adee0da05d4d228481c9200518fcb1b53a65d4156R74-R77)

    **Code analysis improvements:**

    * Added configuration to both native and managed projects
    (`PowerToys.MeasureToolCore.vcxproj`, `MeasureToolUI.csproj`) to
    suppress specific warnings (81010002) and exclude NuGet cache files from
    code analysis, reducing noise and improving build performance.
    [[1]](diffhunk://#diff-76320b3a74a9241df46edb536ba0f817d7150ddf76bb0fe677e2b276f8bae95aL3-R18)
    [[2]](diffhunk://#diff-4f2b49a1a5cc7da36ee6d5044792ef681fd0ea5bea12db9ebd4c3090680d4b07R6-R11)

    **Project reference and output handling:**

    * Updated the managed project (`MeasureToolUI.csproj`) to handle native
    project outputs more robustly, ensuring the WinMD and DLL files are
    available at runtime and configuring the project reference to avoid
    assembly reference issues.

    **Compiler configuration:**

    * Enhanced C++ compiler settings in `Cpp.Build.props` to treat
    angle-bracket includes as external, disable warnings and analysis for
    external headers, and optimize build performance.

commit 7e791f2815
Author: Dave Rayment <dave.rayment@gmail.com>
Date:   Mon Dec 8 01:45:46 2025 +0000

    [ImageResizer] Fix Fill mode not cropping image when Shrink Only was engaged and scale was 1 (#43855)

    ## Summary of the Pull Request
    This PR fixes an Image Resizer issue where **Fill** mode operations were
    silently aborted when **Shrink Only** was enabled (the default) and
    scale was 1.0 on one dimension, resulting in files that were renamed
    according to the intended target size but which actually contained the
    original, unmodified image.

    This also fixes a latent bug regarding square images and the **Ignore
    Orientation** setting, and improves the readability of the core
    `Transform` method.

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes: #43772
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments
    ### Fix **Shrink Only** logic preventing the correct cropping of images
    **Issue:**
    When using **Fill** mode, the scaling factor is calculated based on the
    larger dimension to ensure the image fills the target box. In scenarios
    where one dimension matches the target and the other overflows (e.g.
    shrinking a 100x100 pixel image to 50x100), the calculated scale factor
    is `1.0`.

    The previous `ShrinkOnly` logic included this:

    ```csharp
    if (_settings.ShrinkOnly
            && _settings.SelectedSize.Unit != ResizeUnit.Percent
            && (scaleX >= 1 || scaleY >= 1))
        {
            return source;
        }
    ```

    This correctly prevents `ShrinkOnly` operations from returning upscaled
    result images, but it also exits too early for cases where the user is
    cropping the image across one dimension only, leaving the other at scale
    1. Effectively, the later cropping code is never run and instead of
    returning the cropped image, the original is returned. The _intended_
    target dimensions are correct, which results in the filename parts not
    matching the resulting image size.

    **Fix:**
    The logic has been split between upscaling and cropping, so:

    1. If the scale on either dimension is > `1.0`, return the source
    (explicitly preventing upscaling for **Shrink Only** mode).
    2. If the scale is <= `1.0` then check if the original dimensions exceed
    the target dimensions. If a crop is required, proceed with it even if
    the scale is exactly `1.0`.

    ### Fix for square images triggering orientation swap
    **Issue:**
    The "Ignore Orientation" check in the original code used a compound
    boolean check:

    ```csharp
    (originalWidth < originalHeight != width < height)
    ```

    This clever but less than readable statement detects orientation
    mismatches. The section also includes a logic issue. When the original
    image was square, `originalWidth < originalHeight` evaluated to `false`,
    treating it as Landscape. If the target dimensions were Portrait, the
    logic detected a mismatch and swapped the target dimensions incorrectly,
    which would crop the height instead of the width.

    'Fortunately' this bug was masked by the first bug, as the crop code
    would never be reached anyway.

    **Fix:**
    The orientation detection routine was refactored to explicitly check for
    Landscape vs. Portrait states. Square images are now naturally excluded,
    as they have neither Landscape nor Portrait orientations. This now
    prevents the dimensions from being swapped.

    ### Refactoring/readability
    The main `Transform` method has been cleaned up:

    - Replaced widespread use of `var` with `double` and `int` for dimension
    and scale calculations.
    - Replaced the non-obvious XOR orientation check (`a < b != c < d`) with
    named booleans (`isInputLandscape`, `isTargetPortrait` etc.) to make the
    intent more self-documenting.
    - New and expanded comments throughout.

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed
    Three new unit tests have been added to `ResizeOperationTests.cs` to
    cover the **Fill** mode edge cases:

    1. `TransformHonorsFillWithShrinkOnlyWhenCropRequired`: Verifies than an
    image requiring a crop but no scaling is processed correctly (tests that
    the original bug report is resolved).
    2. `TransformHonorsFillWithShrinkOnlyWhenUpscaleAttempted`: Confirms
    that when `ShrinkOnly` is set, any upscaling operations are still
    blocked.
    3. `TransformHonorsFillWithShrinkOnlyWhenNoChangeRequired`: Verifies
    that the system returns the source if neither scaling nor cropping is
    required.

    I also manually verified the bug fix with a test 4000 x 6000 pixel
    source file with 1920 x `Auto` **Fill** mode and **Shrink Only**
    settings, mirroring the original user's settings, and their source and
    target dimensions.

commit 2b0ecc2979
Author: Noraa Junker <noraa.junker@outlook.com>
Date:   Sun Dec 7 19:36:05 2025 +0100

    Quick accent character set fixes (#43504)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request
    * Fix double uppercase theta character
    * Fix some redundant special symbols

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes: #43457 #43137 #41570
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

commit 45cf3de15d
Author: Jiří Polášek <me@jiripolasek.com>
Date:   Sun Dec 7 10:18:02 2025 +0100

    CmdPal: Fix a line-break in RDC extension error toasts (#44129)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request

    This PR fixes a line break in the RDC extension toast message, replacing
    unescaped \r with a new line (\r in the XML is not recognized as a new
    line escape sequence).

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit bf8c548501
Author: Jiří Polášek <me@jiripolasek.com>
Date:   Sun Dec 7 10:10:45 2025 +0100

    CmdPal: Make text of text Settings button on Command Bar localizable (#44128)

    ## Summary of the Pull Request

    See title

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes: #44108
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 121c6c0712
Author: Carlos Rafael Ramirez <crramirez@users.noreply.github.com>
Date:   Sun Dec 7 02:54:10 2025 +0100

    Add RGB hex color preview to Advanced Paste clipboard history (#43990)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request

    This pull request adds support for recognizing and displaying clipboard
    items that are valid RGB hex color codes (such as `#FFBFAB` or `#abc`)
    in the Advanced Paste module. It introduces logic to detect hex color
    strings, converts them to color values, and updates the UI to show a
    color preview for these items. The changes also include comprehensive
    unit tests for the new functionality.

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes: #43538
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [x] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [x] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    **Clipboard color detection and conversion:**

    * Added `ClipboardItemHelper.IsRgbHexColor` method using a compiled
    regex to identify valid hex color strings in clipboard text.
    [[1]](diffhunk://#diff-7429196ad30cd0bce57b102669da4dc13d43a09579e99ceac7cc0f7dc101cd2bR62-R86)
    [[2]](diffhunk://#diff-7429196ad30cd0bce57b102669da4dc13d43a09579e99ceac7cc0f7dc101cd2bR112-R114)
    * Introduced `HexColorConverterHelper.ConvertHexColorToRgb` utility to
    convert hex color strings to `Windows.UI.Color`, handling both 3-digit
    and 6-digit formats.

    **UI enhancements for color previews:**

    * Updated `ClipboardHistoryItemPreviewControl` to include a color
    preview grid that displays an ellipse filled with the detected color and
    the color code as text, using the new `HexColorToBrushConverter`.
    [[1]](diffhunk://#diff-2ed6014d4c17037b9cd0ab397e40b9069b1e7fe47a700673f34e8217d78124d5R29-R48)
    [[2]](diffhunk://#diff-2ed6014d4c17037b9cd0ab397e40b9069b1e7fe47a700673f34e8217d78124d5R14)
    [[3]](diffhunk://#diff-0c26c92697f6bb38fa40160fc8b18f0876ddc8d828a510034411001aa2e05063R1-R28)
    * Modified logic in `ClipboardHistoryItemPreviewControl.xaml.cs` to
    ensure color previews are shown only for detected color items and to
    adjust visibility of text and glyph previews accordingly.

    **Unit tests for color detection and conversion:**

    * Added unit tests for hex color conversion
    (`HexColorToColorConverterTests.cs`) and color detection logic
    (`ClipboardItemHelperTests.cs`) to verify correct behavior for valid,
    invalid, and edge-case inputs.
    [[1]](diffhunk://#diff-d81d997d5fb414f1563c31c38681113aaa9c847ef05bb77662d30bd1310d6b8eR1-R61)
    [[2]](diffhunk://#diff-185e8954ca6f061bf5d60d0c61ac6cfd87bd1a48ebda11a8172e3496a050fe85R1-R36)

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed
    * Copied to the clipboard a color encoded text like: #FFBFAB
    * Opened Advanced Paste and noticed the color:

    <img width="467" height="309" alt="image"
    src="https://github.com/user-attachments/assets/6cedce89-9833-4efb-abf9-3cfe8e8f32f0"
    />

    ---------

    Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
    Co-authored-by: crramirez <8397379+crramirez@users.noreply.github.com>
    Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

commit e68526b8d8
Author: Jiří Polášek <me@jiripolasek.com>
Date:   Fri Dec 5 23:32:24 2025 +0100

    CmdPal: Add configuration option for Escape key behavior (#43354)

    ## Summary of the Pull Request

    This PR adds a new option to the **General** page in **Settings**:

    Escape key behavior — a dropdown with the following choices:

    - Clear search first, then go back
      - Current behavior.
      - If the search box contains text, it is cleared; otherwise goes back.
      - On the home page, CmdPal is dismissed.

    - Go back
      - Leaves the search text intact.
    - If the page is not transient, the search text reappears when
    returning.
      - On the home page, CmdPal is dismissed.

    - Hide window and go home (Always dismiss)
      - Immediately dismisses CmdPal and navigates to the home page.
      - Ignores the **Go home when activated** setting.
      - Search text is cleared.

    - Hide window
      - Just hides the window.
      - Intended to be used with #43355.

    This implementation preserves existing behavior, except for **Always
    dismiss**, which always forces navigation to the home page.

    ## Pictures? Pictures!

    <img width="1305" height="892" alt="image"
    src="https://github.com/user-attachments/assets/562e5604-1da6-4fc6-8358-5053df9c573d"
    />

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes: #38311
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 995a699de7
Author: ruslanlap <106077551+ruslanlap@users.noreply.github.com>
Date:   Fri Dec 5 18:21:01 2025 +0200

    [PowerToysRun][Docs] Add QuickAI plugin to third-party plugins list (#43238)

    Adds QuickAI plugin to the third-party plugins documentation.

    QuickAI is an AI-powered assistance plugin that provides instant, smart
    responses from multiple providers (Groq, Together, Fireworks,
    OpenRouter, Cohere) directly in PowerToys Run.

    Repository: https://github.com/ruslanlap/PowerToysRun-QuickAi

    ---------

    Co-authored-by: Niels Laute <niels.laute@live.nl>

commit 5f6df35d8d
Author: Copilot <198982749+Copilot@users.noreply.github.com>
Date:   Fri Dec 5 10:20:33 2025 -0600

    Add semantic headings to Dashboard page for accessibility (#42438)

    ## Summary

    Fixes #37668 by adding proper semantic heading structure to the
    Dashboard (Home) page, enabling screen reader users to navigate the page
    efficiently using heading shortcuts.

    ## Problem

    The Dashboard page lacked semantic heading elements, making it difficult
    for users of assistive technologies to understand the page structure and
    navigate between sections. When using screen readers with heading
    navigation (H key in scan mode), no headings were announced, violating
    WCAG 2.2 Success Criterion 1.3.1 (Info and Relationships).

    ## Solution

    Added `AutomationProperties.HeadingLevel` attributes to provide proper
    heading hierarchy:

    1. **Dashboard Title** - Marked as Level 1 (H1) heading
    - Added `AutomationProperties.HeadingLevel="1"` to the "Home" page title
       - Follows the same pattern as `SettingsPageControl.xaml`

    2. **Card Titles** - Marked as Level 2 (H2) headings
    - Added `AutomationProperties.HeadingLevel="Level2"` to the Card
    component
    - Applies to all card sections: "Quick Access", "Shortcuts Overview",
    and "Utilities"
       - Follows the same pattern as `SettingsGroup.xaml`

    ## Resulting Structure

    ```
    H1: Home (Dashboard Title)
    ├─ H2: Quick Access
    ├─ H2: Shortcuts Overview
    └─ H2: Utilities
    ```

    ## Impact

    - Screen reader users can now use heading navigation (H key) to jump
    between sections on the Dashboard page
    - Provides proper document structure that follows WCAG 2.2 Level A
    guidelines
    - No visual or functional changes - only accessibility metadata added
    - Consistent with existing accessibility patterns used throughout the
    Settings UI

    ## Testing

    - Changes follow existing patterns in `SettingsPageControl.xaml` (Level
    1) and `SettingsGroup.xaml` (Level 2)
    - Only XAML accessibility attributes added - no code logic changes
    - Minimal, surgical changes: 2 lines across 2 files

    ## References

    - Issue: #37668
    - WCAG 2.2: [Success Criterion 1.3.1 - Info and
    Relationships](https://www.w3.org/WAI/WCAG22/Understanding/info-and-relationships)

    <!-- START COPILOT CODING AGENT SUFFIX -->

    <details>

    <summary>Original prompt</summary>

    >
    > ----
    >
    > *This section details on the original issue you should resolve*
    >
    > <issue_title>No Heading Defined on the Home Page.</issue_title>
    > <issue_description>### Microsoft PowerToys version
    >
    > v0.94.2
    >
    > ### Installation method
    >
    > PowerToys auto-update
    >
    > ### Area(s) with issue?
    >
    > New+
    >
    > ### Steps to reproduce
    >
    > **Repro Steps:**
    >
    > 1. Open the Power Toys.
    > 2. Now Select Home from the left navigation pane.
    > 3. Now Turn on narrator and turn on scan mode.
    > 4. Now use Quick navigation H key for headings.
    > 5. Observe the issue.
    >
    > ### ✔️ Expected Behavior
    >
    > The home page should contain at least one semantic heading (typically
    an <h1>) that describes the main topic or purpose of the page.
    >
    > ###  Actual Behavior
    >
    > The home page does not contain any semantic heading tags (e.g., <h1>,
    <h2>, etc.). While text may be visually styled to look like headings, no
    actual heading elements are present in the page’s HTML structure.
    >
    > ### Additional Information
    >
    > **User Impact:**
    > Users of screen readers and other assistive technologies rely on
    headings to understand the structure of the page and navigate
    efficiently.
    >
    > **WCAG Reference:**
    > https://www.w3.org/WAI/WCAG22/Understanding/info-and-relationships
    >
    > **Attachments:**
    >
    >
    https://github.com/user-attachments/assets/5140b50c-67fc-40d5-bf80-40e2a2bb7782
    >
    > ### Other Software
    >
    > _No response_</issue_description>
    >
    > ## Comments on the Issue (you are @copilot in this section)
    >
    > <comments>
    > </comments>
    >

    </details>

    Fixes microsoft/PowerToys#42421

    <!-- START COPILOT CODING AGENT TIPS -->
    ---

    💡 You can make Copilot smarter by setting up custom instructions,
    customizing its development environment and configuring Model Context
    Protocol (MCP) servers. Learn more [Copilot coding agent
    tips](https://gh.io/copilot-coding-agent-tips) in the docs.

    ---------

    Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
    Co-authored-by: niels9001 <9866362+niels9001@users.noreply.github.com>
    Co-authored-by: Niels Laute <niels.laute@live.nl>

commit cffdecbc1b
Author: Noraa Junker <aaron.junker@outlook.com>
Date:   Fri Dec 5 14:55:45 2025 +0100

    Add documentation of bot commands and fix some devdocs (#43399)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request

    * Fixes location of `style.md` file
    * Deletes duplicated `localization.md` file
    * Adds documentation about the bot commands.
    * Adds links to aka.ms link docs and the new document

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [x] **Dev docs:** Added/updated

commit a4d8405957
Author: Noraa Junker <aaron.junker@outlook.com>
Date:   Fri Dec 5 14:54:13 2025 +0100

    Fix dpi issues in Quick Accent (#43314)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes: #40865
    - [x] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit cdf66a70e9
Author: Niels Laute <niels.laute@live.nl>
Date:   Fri Dec 5 14:33:59 2025 +0100

    [AdvancedPaste] Fix outdated string in Settings (#44099)

    Updating and removing outdated strings.

    Updated string:

    <img width="1565" height="323" alt="image"
    src="https://github.com/user-attachments/assets/3dcad3b9-7ba9-4d87-ab36-405a8e1705db"
    />

commit 9dcddfd4b8
Author: Valentin Arthur Thomas <64769541+warquys@users.noreply.github.com>
Date:   Fri Dec 5 11:57:01 2025 +0100

    Quotation mark (#30481)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Add Quotation mark
    Add local quotation based on ~~VK_OEM_7(0xDE)~~ VK_OEM_COMMA(0xBC) key.
    Not all quotes have been added, only `‟ „ ” « » ‚ , ‘ ’ › ‹ '「 」 《 》 『
    』〈 〉″ ‴ ⁗`
    Why not added :
    - ` ⹂ ⌜ ⌝ ❛ ❜ ❝ ❞ 🙶 🙷 🙸 ' 「 」 ` its redundant and would make too much
    and not readable.
    - ` ﹁ ﹂ ﹃ ﹄ `  I did not put them because there use for horizontal text

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes: https://github.com/microsoft/PowerToys/issues/29371
    https://github.com/microsoft/PowerToys/issues/24832
    - [ ] **Communication:** I've discussed this with core contributors
    already. If work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end user facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places (None)
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed
    or any additional comments/features here -->
    This PR is currently a draft, I still need to know if adding
    language-related keyboard management is a good idea or specifying the
    use of a gobal key to make it easier to manage all the keyboards in one.
    Some languages ​​can use different keyboards, I think this would become
    problematic if the keyboard does not match the key used by default.
    However, using a universal key can also pose an issue to finding the
    key. that remains to be discussed
    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 503bcbdf2d
Author: Copilot <198982749+Copilot@users.noreply.github.com>
Date:   Fri Dec 5 07:33:37 2025 +0100

    Restore missing "Quick access" menu item in tray icon context menu (#42676)

    ## Summary
    Restores the "Quick access" menu item that was accidentally removed from
    the PowerToys tray icon context menu.

    ## Issue
    Fixes #[issue_number]

    The "Quick access" menu item was missing from the tray icon's
    right-click context menu, preventing users from accessing this feature
    via the tray menu.

    **Expected menu:**

    ![Expected
    menu](https://github.com/user-attachments/assets/805b1436-5a08-42e7-a34d-b9848fd9a235)

    **Actual menu (before this fix):**

    ![Actual
    menu](https://github.com/user-attachments/assets/7584035d-e893-4f73-acc3-84d789e31e81)

    ## Changes
    - Added the missing `MENUITEM "Quick access\tLeft-click",
    ID_QUICK_ACCESS_MENU_COMMAND` entry as the first menu item in the
    `ID_TRAY_MENU` definition in `src/runner/runner.base.rc`

    ## Details
    The menu item was accidentally removed in commit
    f5797a065a. This PR restores it to its
    correct position as the first item in the tray menu.

    All supporting code was already in place:
    - The resource ID `ID_QUICK_ACCESS_MENU_COMMAND` (40006) is defined in
    `resource.base.h`
    - The resource string `QUICK_ACCESS_MENU_TEXT` is defined in
    `Resources.resx`
    - The menu command handler in `tray_icon.cpp` opens the Quick Access
    flyout window
    - The localization code updates the menu text at runtime

    ## Testing
    -  Verified the menu item syntax is correct and matches existing
    patterns
    -  Confirmed all supporting resource IDs and handler code exist
    -  CI build verification pending

    After this fix, the tray menu will correctly display:
    1. Quick access (Left-click)
    2. Settings (Double-click)
    3. Documentation
    4. Report Bug
    5. Close

    <!-- START COPILOT CODING AGENT SUFFIX -->

    <details>

    <summary>Original prompt</summary>

    >
    > ----
    >
    > *This section details on the original issue you should resolve*
    >
    > <issue_title>Quick Access missing in tray menu</issue_title>
    > <issue_description>### Microsoft PowerToys version
    >
    > 0.95.0
    >
    > ### Installation method
    >
    > PowerToys auto-update
    >
    > ### Area(s) with issue?
    >
    > System tray interaction
    >
    > ### Steps to reproduce
    >
    > 1. Right click the tray icon
    > 2. Look at the list of items which can be selected
    > 3. Notice that the "Quick access" is missing
    >
    > Expected menu ("Exit" is now "Close" I took this image from initial
    implementation):
    >
    > <img width="234" height="127" alt="Image"
    src="https://github.com/user-attachments/assets/805b1436-5a08-42e7-a34d-b9848fd9a235"
    />
    >
    > Actual menu right now:
    >
    > <img width="239" height="105" alt="Image"
    src="https://github.com/user-attachments/assets/7584035d-e893-4f73-acc3-84d789e31e81"
    />
    >
    > ### ✔️ Expected Behavior
    >
    > The "Quick access" menu item should be there
    >
    > ###  Actual Behavior
    >
    > The menu item is missing
    >
    > ### Additional Information
    >
    > Windows 10 Pro 22H2 19045.6332
    >
    > (Also it is the same on my other computers)
    >
    > ### Other Software
    >
    > _No response_</issue_description>
    >
    > <agent_instructions>restore
    >
    > MENUITEM "Quick access\tLeft-click", ID_QUICK_ACCESS_MENU_COMMAND
    >
    > as first menu item of ID_TRAY_MENU MENU in
    src/runner/runner.base.rc</agent_instructions>
    >
    > ## Comments on the Issue (you are @copilot in this section)
    >
    > <comments>
    > <comment_new><author>@niels9001</author><body>
    > @davidegiacometti is this a regression from the PR where we updated
    the string names?</body></comment_new>
    > <comment_new><author>@davidegiacometti</author><body>
    > Hi @niels9001
    > I just realized that the menu was missing in
    https://github.com/microsoft/PowerToys/pull/40714 screenshots, but the
    regression was caused by
    f5797a065a.
    > Unfortunately, many of the `.rc` files in the PT codebase have
    UTF16-LE encoding and GitHub doesn't show diff.</body></comment_new>
    > </comments>
    >

    </details>

    Fixes microsoft/PowerToys#42618

    <!-- START COPILOT CODING AGENT TIPS -->
    ---

    💬 Share your feedback on Copilot coding agent for the chance to win a
    $200 gift card! Click
    [here](https://survey3.medallia.com/?EAHeSx-AP01bZqG0Ld9QLQ) to start
    the survey.

    ---------

    Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
    Co-authored-by: davidegiacometti <25966642+davidegiacometti@users.noreply.github.com>

commit 52f2561937
Author: Jiří Polášek <me@jiripolasek.com>
Date:   Wed Dec 3 17:16:25 2025 +0100

    CmdPal: Find app for WinGet package (#43943)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request

    This PR introduces a bit of dark magic to resolve the correct installed
    app for a given WinGet package:

    - Packaged apps: matched using their package family name.
    - Everything else: matched using the product code (GUID) and heuristic
    registry lookup.
    - The registry rarely stores the executable path directly, so the logic
    compares install locations with known apps.
      - It attempts to pick the best candidate while avoiding uninstallers.
      - It’s not science — let’s call it `#666666` magic.
    - MSI API support was removed because it's too slow for this scenario.
    - If no reliable match is found, the command is skipped for now. The
    future plan is to redirect the user to the list of installed apps and
    search by display name, but that needs some supporting infrastructure
    first.
    - The command order for WinGet list entries was updated: **Install /
    Uninstall** is now the primary action, ensuring a stable UI since this
    command is always available.

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes: #43671
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit dc30f3fd8e
Author: Dustin L. Howett <duhowett@microsoft.com>
Date:   Wed Dec 3 03:59:46 2025 -0600

    build: move main and setup to SLNX (#43478)

    Closes #37100

    This does not migrate the rest of the solutions (why do we have so
    many?)

    Not migrated:

    - TemplateCmdPalExtension.sln
    - FancyZonesEditor.sln
    - BugReportTool.sln
    - CleanUp_tool.sln
    - FancyZones_DrawLayoutTest.sln
    - FancyZones_zonable_tester.sln
    - FancyZone_HitTest.sln
    - MonitorReportTool.sln
    - PowerToyTemplate.sln
    - StylesReportTool.sln

    ---------

    Co-authored-by: vanzue <vanzue@outlook.com>

commit 8f9a2c32cc
Author: Jessica Dene Earley-Cha <12740421+chatasweetie@users.noreply.github.com>
Date:   Tue Dec 2 09:59:57 2025 -0800

    add missing powertoys events (#44016)

    ## Summary of the Pull Request
    This added missing telemetry events from modules that were not listed in
    DATA_AND_PRIVACY

    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [x] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected

commit bcd1583bb7
Author: moooyo <42196638+moooyo@users.noreply.github.com>
Date:   Tue Dec 2 16:31:02 2025 +0800

    [AOT] Refactor SettingsLib/SettingsUI for Native AOT compatibility (#42644)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request

    Key Changes:

    1. Settings.UI.Library:
    - Added SettingsSerializationContext.cs with comprehensive
    JsonSerializable attributes for all settings types
    - Updated BasePTModuleSettings.ToJsonString() to use AOT-compatible
    serialization
    - Updated SettingsUtils.GetFile<T>() to use AOT-compatible
    deserialization
    - Modified all ToString() methods in Properties classes to use
    SettingsSerializationContext
    - Converted struct fields to properties in SunTimes and
    MouseWithoutBordersProperties for serialization compatibility

    2. Settings.UI:
    - Fixed namespace alias in SourceGenerationContextContext.cs to avoid
    conflicts

    For any future developers who discover incorrect settings resolution,
    please follow up my changes to add your setting type into
    JsonSerilizerContext.

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

    Co-authored-by: Yu Leng <yuleng@microsoft.com>

commit b075a021df
Author: Carlos Zamora <carlos.zamora@microsoft.com>
Date:   Mon Dec 1 22:09:08 2025 -0800

    Bump our telemetry package version (#44015)

    Data collection is still hard.

    This just makes it so that the build pipeline uses the updated PowerToys
    telemetry NuGet package. The updated package switches us over to use a
    diagnostic data provider group for compliance with some new regulations
    (i.e. DMA and EU Data Act).

commit 9e43c23216
Author: Michael Clayton <mike@kingslandconsulting.co.uk>
Date:   Tue Dec 2 02:43:08 2025 +0000

    Ready for Review - [Mouse Without Borders] - refactoring "Common" classes (Part 6 of 7)  (#43208)

    ## Summary of the Pull Request

    **Part 6** of a [slow-running 7-part
    refactor](https://github.com/microsoft/PowerToys/issues/35155#issuecomment-2583334110)
    of the giant "Common" class in Mouse Without Borders into individual
    classes with tighter private scope.

    In this PR:

    * Extract the "Common" code from the following files:
      * ```Common.Encryption.cs```-> ```Core/Encryption.cs```
      * ```Common.Package.cs``` -> ```Core/<multiple files>.cs```
    * ```Common.ShutdownWithPowerToys.cs``` ->
    ```Core/ShutdownWithPowerToys.cs```
      * ```Common.VK.cs``` -> ```Core/VK.cs```, ```Core/WM.cs```
      * ```Common.WinAPI.cs``` -> ```Core/WinAPI.cs```
    * Update references to the types in the new locations
    * Update unit test to verify functionality has only changed in an
    expected way

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x]      Partially addresses #35155
    - [x] **Communication:** I've discussed this with core contributors
    already. If work hasn't been agreed, this work might be rejected
    - [x]     **Tests:** Added/updated and all pass
    - [x]     **Localization:** All end user facing strings can be localized
       - no changes in this PR
    - [x]     **Dev docs:** Added/updated
       - no changes in this PR
    - [x]     **New binaries:** Added on the required places
       - no changes in this PR
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [x] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx
       - no changes in this PR

    <!-- Provide a more detailed description of the PR, other things fixed
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

    ### Run manual tests from [Test Checklist
    Template](5bc7201ae2/doc/releases/tests-checklist-template.md (mouse-without-borders)):

    * Install PowerToys on two PCs in the same local network:
       - [x]     Verify that PowerToys is properly installed on both PCs.
       - [x]     Configure Windows Firewall Rules
    - ```netsh advfirewall firewall add rule
    name="PowerToys.MouseWithoutBorders - mc" dir=in action=allow
    program="C:\src\mc\PowerToys\x64\Debug\PowerToys.exe" enable=yes
    remoteip=any profile=any protocol=tcp```

     * Setup Connection:
    - [x] Open MWB's settings on the first PC and click the "New Key"
    button. Verify that a new security key is generated.
    - [x] Copy the generated security key and paste it in the corresponding
    input field in the settings of MWB on the second PC. Also enter the name
    of the first PC in the required field.
    - [x] Press "Connect" and verify that the machine layout now includes
    two PC tiles, each displaying their respective PC names.

     * Verify Connection Status:
    - [x] Ensure that the border of the remote PC turns green, indicating a
    successful connection.
    - [x] Enter an incorrect security key and verify that the border of the
    remote PC turns red, indicating a failed connection.

     * Test Remote Mouse/Keyboard Control:
    - [x] With the PCs connected, test the mouse/keyboard control from one
    PC to another. Verify that the mouse/keyboard inputs are correctly
    registered on the other PC.
    - [ ] Test remote mouse/keyboard control across all four PCs, if
    available. Verify that inputs are correctly registered on each connected
    PC when the mouse is active there.
         - unable to test - only 2 machines available

     * Test Remote Control with Elevated Apps:
    - note - the main PowerToys.exe must be running as a **non**-admin for
    these tests
    - [x] Open an elevated app on one of the PCs. Verify that without "Use
    Service" enabled, PowerToys does not control the elevated app.
    - [x] Enable "Use Service" in MWB's settings (need to run PowerToys.exe
    as admin to enable "Use Service", then restart PowerToys.exe as
    non-admin). Verify that PowerToys can now control the elevated app
    remotely. Verify that MWB processes are running as LocalSystem, while
    the MWB helper process is running non-elevated.
    - ```get-process -Name "PowerToys.MouseWithoutBorders*" -IncludeUserName
    | format-table Id, ProcessName, UserName```
    - [x] Process: ```PowerToys.MouseWithoutBorders.exe``` - running as
    ```SYSTEM```
    - [x] Process: ```PowerToys.MouseWithoutBorders.Helper.exe``` - running
    as current user
    - ```get-service -Name "PowerToys.*" | ft Status, Name, UserName;
    get-ciminstance -Class "Win32_Service" -Filter "Name like 'PowerToys%'"
    | ft ProcessId, Name```
    - [x] Service: ```PowerToys.MWB.Service``` - running as ```Local
    System```
    - [x] Toggle "Use Service" again, verify that each time you do that, the
    MWB processes are restarted.
    - [x] Run PowerToys elevated on one of the machines, verify that you can
    control elevated apps remotely now on that machine.

    * Test Module Enable Status:
    - [x] For all combinations of "Use Service"/"Run PowerToys as admin",
    try enabling/disabling MWB module and verify that it's indeed being
    toggled using task manager.

     * Test Disconnection/Reconnection:
    - [x] Disconnect one of the PCs from network. Verify that the machine
    layout updates to reflect the disconnection.
       - [x]     Do the same, but now by exiting PowerToys.
       - [ ]     Start PowerToys again, verify that the PCs are reconnected.

     * Test Various Local Network Conditions:
    - [ ] Test MWB performance under various network conditions (e.g., low
    bandwidth, high latency). Verify that the tool maintains a stable
    connection and functions correctly.

     * Clipboard Sharing:
    - [x] Copy some text on one PC and verify that the same text can be
    pasted on another PC.
    - [x] Use the screenshot key and Win+Shift+S to take a screenshot on one
    PC and verify that the screenshot can be pasted on another PC.
    - [x] Copy a file in Windows Explorer and verify that the file can be
    pasted on another PC. Make sure the file size is below 100MB.
    - [x] Try to copy multiple files and directories and verify that it's
    not possible (only the first selected file is being copied).

     * Drag and Drop:
    - [ ] Drag a file from Windows Explorer on one PC, cross the screen
    border onto another PC, and release it there. Verify that the file is
    copied to the other PC. Make sure the file size is below 100MB.
    - [ ] While dragging the file, verify that a corresponding icon is
    displayed under the mouse cursor.
    - [ ] Without moving the mouse from one PC to the target PC, press
    CTRL+ALT+F1/2/3/4 hotkey to switch to the target PC directly and verify
    that file sharing/dropping is not working.

     * Lock and Unlock with "Use Service" Enabled:
       - [x]     Enable "Use Service" in MWB's settings.
    - [x] Lock a remote PC using Win+L, move the mouse to it remotely, and
    try to unlock it. Verify that you can unlock the remote PC.
    - [x] Disable "Use Service" in MWB's settings, lock the remote PC, move
    the mouse to it remotely, and try to unlock it. Verify that you can't
    unlock the remote PC.

     * Test Settings:
    - [ ] Change the rest of available settings on MWB page and verify that
    each setting works as described.

    ### Group Policy Tests

    See https://learn.microsoft.com/en-us/windows/powertoys/grouppolicy

    - [ ] Install *.admx / *.adml and check settings behave as expected
      - [ ] I'll expand the list of settings here when I get this far :-)
    - [ ] HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys
      - [x]     ConfigureEnabledUtilityMouseWithoutBorders
    - [x] ```[missing]``` - "Activation -> Enable Mouse Without Borders"
    enabled, with GPO warning hidden
    - ```reg delete HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v
    ConfigureEnabledUtilityMouseWithoutBorders /f```
    - [x] ```0``` - "Activation -> Enable Mouse Without Borders" set to
    "off" and disabled, with GPO warning visible
    - ```reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v
    ConfigureEnabledUtilityMouseWithoutBorders /t REG_DWORD /d 0 /f```
    - [x] ```1``` - "Activation -> Enable Mouse Without Borders" set to "on"
    and disabled, with GPO warning visible
    - ```reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v
    ConfigureEnabledUtilityMouseWithoutBorders /t REG_DWORD /d 1 /f```
      - [ ] MwbClipboardSharingEnabled
      - [ ] MwbFileTransferEnabled
      - [ ] MwbUseOriginalUserInterface
      - [ ] MwbDisallowBlockingScreensaver
      - [ ] MwbSameSubnetOnly
      - [ ] MwbValidateRemoteIp
      - [x]     MwbDisableUserDefinedIpMappingRules
    - [x] ```[missing]``` - "Advanced Settings -> IP address mapping"
    enabled, with GPO warning hidden
    - ```reg delete HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v
    MwbDisableUserDefinedIpMappingRules /f```
    - [x] ```0``` - "Advanced Settings -> IP address mapping" enabled, with
    GPO warning hidden
    - ```reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v
    MwbDisableUserDefinedIpMappingRules /t REG_DWORD /d 0 /f```
    - [x] ```1``` - "Advanced Settings -> IP address mapping" disabled, with
    GPO warning visible
    - ```reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v
    MwbDisableUserDefinedIpMappingRules /t REG_DWORD /d 1 /f```
      - [x]     MwbPolicyDefinedIpMappingRules
    - [x] ```[missing]``` - "Advanced Settings -> IP address mapping"
    enabled, with GPO warning and GPO values hidden
    - ```reg delete HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v
    MwbPolicyDefinedIpMappingRules /f```
    - [x] ```[empty value]``` - "Advanced Settings -> IP address mapping"
    enabled, with GPO warning hidden and GPO values hidden
    - ```reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v
    MwbPolicyDefinedIpMappingRules /t REG_MULTI_SZ /d "" /f```
    - [x] ```[non-empty value]``` - "Advanced Settings -> IP address
    mapping" enabled, with GPO warning visible and GPO values visible
    - ```reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v
    MwbPolicyDefinedIpMappingRules /t REG_MULTI_SZ /d "aaa 10.0.0.1\0bbb
    10.0.0.2" /f```

commit bece9c9217
Author: Jiří Polášek <me@jiripolasek.com>
Date:   Tue Dec 2 03:25:38 2025 +0100

    CmdPal: Adds a back button to Settings window (#44013)

    ## Summary of the Pull Request

    This PR introduces proper navigation support in the Settings window.
    - Enables the Go back button in the title bar.
    - Adds support for Alt + Left Arrow, mouse X1 button, and the Go back
    button.
    - Fixes breadcrumb updates and localization issues to prevent them from
    breaking during navigation.

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes: #44011
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 32c13cead4
Author: Jiří Polášek <me@jiripolasek.com>
Date:   Mon Dec 1 20:24:54 2025 +0100

    CmdPal: Remove fallbacks from the home page when there's no query (#44005)

    ## Summary of the Pull Request

    This PR stops fallback commands from showing on the homepage when
    there’s no query, with the reasons detailed in the linked issue.

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes: #44004
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 33808fdb9c
Author: Jiří Polášek <me@jiripolasek.com>
Date:   Mon Dec 1 20:23:48 2025 +0100

    CmdPal: Hide RDC fallback item by default (#43994)

    ## Summary of the Pull Request

    This fixes few nits with RDC extension:
    - hides the RDC fallback item from the home page when there’s no query;
    - fixes MSTSC process working directory (must physically exists or be an
    empty string)

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit f510be4c53
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Mon Dec 1 22:29:21 2025 +0800

    Build(deps): Bump actions/checkout from 3 to 6 (#43838)

    Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to
    6.
    <details>
    <summary>Release notes</summary>
    <p><em>Sourced from <a
    href="https://github.com/actions/checkout/releases">actions/checkout's
    releases</a>.</em></p>
    <blockquote>
    <h2>v6.0.0</h2>
    <h2>What's Changed</h2>
    <ul>
    <li>Update README to include Node.js 24 support details and requirements
    by <a href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a>
    in <a
    href="https://redirect.github.com/actions/checkout/pull/2248">actions/checkout#2248</a></li>
    <li>Persist creds to a separate file by <a
    href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/2286">actions/checkout#2286</a></li>
    <li>v6-beta by <a
    href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/2298">actions/checkout#2298</a></li>
    <li>update readme/changelog for v6 by <a
    href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/2311">actions/checkout#2311</a></li>
    </ul>
    <p><strong>Full Changelog</strong>: <a
    href="https://github.com/actions/checkout/compare/v5.0.0...v6.0.0">https://github.com/actions/checkout/compare/v5.0.0...v6.0.0</a></p>
    <h2>v6-beta</h2>
    <h2>What's Changed</h2>
    <p>Updated persist-credentials to store the credentials under
    <code>$RUNNER_TEMP</code> instead of directly in the local git
    config.</p>
    <p>This requires a minimum Actions Runner version of <a
    href="https://github.com/actions/runner/releases/tag/v2.329.0">v2.329.0</a>
    to access the persisted credentials for <a
    href="https://docs.github.com/en/actions/tutorials/use-containerized-services/create-a-docker-container-action">Docker
    container action</a> scenarios.</p>
    <h2>v5.0.1</h2>
    <h2>What's Changed</h2>
    <ul>
    <li>Port v6 cleanup to v5 by <a
    href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/2301">actions/checkout#2301</a></li>
    </ul>
    <p><strong>Full Changelog</strong>: <a
    href="https://github.com/actions/checkout/compare/v5...v5.0.1">https://github.com/actions/checkout/compare/v5...v5.0.1</a></p>
    <h2>v5.0.0</h2>
    <h2>What's Changed</h2>
    <ul>
    <li>Update actions checkout to use node 24 by <a
    href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/2226">actions/checkout#2226</a></li>
    <li>Prepare v5.0.0 release by <a
    href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/2238">actions/checkout#2238</a></li>
    </ul>
    <h2>⚠️ Minimum Compatible Runner Version</h2>
    <p><strong>v2.327.1</strong><br />
    <a
    href="https://github.com/actions/runner/releases/tag/v2.327.1">Release
    Notes</a></p>
    <p>Make sure your runner is updated to this version or newer to use this
    release.</p>
    <p><strong>Full Changelog</strong>: <a
    href="https://github.com/actions/checkout/compare/v4...v5.0.0">https://github.com/actions/checkout/compare/v4...v5.0.0</a></p>
    <h2>v4.3.1</h2>
    <h2>What's Changed</h2>
    <ul>
    <li>Port v6 cleanup to v4 by <a
    href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/2305">actions/checkout#2305</a></li>
    </ul>
    <p><strong>Full Changelog</strong>: <a
    href="https://github.com/actions/checkout/compare/v4...v4.3.1">https://github.com/actions/checkout/compare/v4...v4.3.1</a></p>
    <h2>v4.3.0</h2>
    <h2>What's Changed</h2>
    <ul>
    <li>docs: update README.md by <a
    href="https://github.com/motss"><code>@​motss</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/1971">actions/checkout#1971</a></li>
    <li>Add internal repos for checking out multiple repositories by <a
    href="https://github.com/mouismail"><code>@​mouismail</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/1977">actions/checkout#1977</a></li>
    <li>Documentation update - add recommended permissions to Readme by <a
    href="https://github.com/benwells"><code>@​benwells</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/2043">actions/checkout#2043</a></li>
    </ul>
    <!-- raw HTML omitted -->
    </blockquote>
    <p>... (truncated)</p>
    </details>
    <details>
    <summary>Changelog</summary>
    <p><em>Sourced from <a
    href="https://github.com/actions/checkout/blob/main/CHANGELOG.md">actions/checkout's
    changelog</a>.</em></p>
    <blockquote>
    <h1>Changelog</h1>
    <h2>V6.0.0</h2>
    <ul>
    <li>Persist creds to a separate file by <a
    href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/2286">actions/checkout#2286</a></li>
    <li>Update README to include Node.js 24 support details and requirements
    by <a href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a>
    in <a
    href="https://redirect.github.com/actions/checkout/pull/2248">actions/checkout#2248</a></li>
    </ul>
    <h2>V5.0.1</h2>
    <ul>
    <li>Port v6 cleanup to v5 by <a
    href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/2301">actions/checkout#2301</a></li>
    </ul>
    <h2>V5.0.0</h2>
    <ul>
    <li>Update actions checkout to use node 24 by <a
    href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/2226">actions/checkout#2226</a></li>
    </ul>
    <h2>V4.3.1</h2>
    <ul>
    <li>Port v6 cleanup to v4 by <a
    href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/2305">actions/checkout#2305</a></li>
    </ul>
    <h2>V4.3.0</h2>
    <ul>
    <li>docs: update README.md by <a
    href="https://github.com/motss"><code>@​motss</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/1971">actions/checkout#1971</a></li>
    <li>Add internal repos for checking out multiple repositories by <a
    href="https://github.com/mouismail"><code>@​mouismail</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/1977">actions/checkout#1977</a></li>
    <li>Documentation update - add recommended permissions to Readme by <a
    href="https://github.com/benwells"><code>@​benwells</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/2043">actions/checkout#2043</a></li>
    <li>Adjust positioning of user email note and permissions heading by <a
    href="https://github.com/joshmgross"><code>@​joshmgross</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/2044">actions/checkout#2044</a></li>
    <li>Update README.md by <a
    href="https://github.com/nebuk89"><code>@​nebuk89</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/2194">actions/checkout#2194</a></li>
    <li>Update CODEOWNERS for actions by <a
    href="https://github.com/TingluoHuang"><code>@​TingluoHuang</code></a>
    in <a
    href="https://redirect.github.com/actions/checkout/pull/2224">actions/checkout#2224</a></li>
    <li>Update package dependencies by <a
    href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/2236">actions/checkout#2236</a></li>
    </ul>
    <h2>v4.2.2</h2>
    <ul>
    <li><code>url-helper.ts</code> now leverages well-known environment
    variables by <a href="https://github.com/jww3"><code>@​jww3</code></a>
    in <a
    href="https://redirect.github.com/actions/checkout/pull/1941">actions/checkout#1941</a></li>
    <li>Expand unit test coverage for <code>isGhes</code> by <a
    href="https://github.com/jww3"><code>@​jww3</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/1946">actions/checkout#1946</a></li>
    </ul>
    <h2>v4.2.1</h2>
    <ul>
    <li>Check out other refs/* by commit if provided, fall back to ref by <a
    href="https://github.com/orhantoy"><code>@​orhantoy</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/1924">actions/checkout#1924</a></li>
    </ul>
    <h2>v4.2.0</h2>
    <ul>
    <li>Add Ref and Commit outputs by <a
    href="https://github.com/lucacome"><code>@​lucacome</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/1180">actions/checkout#1180</a></li>
    <li>Dependency updates by <a
    href="https://github.com/dependabot"><code>@​dependabot</code></a>- <a
    href="https://redirect.github.com/actions/checkout/pull/1777">actions/checkout#1777</a>,
    <a
    href="https://redirect.github.com/actions/checkout/pull/1872">actions/checkout#1872</a></li>
    </ul>
    <h2>v4.1.7</h2>
    <ul>
    <li>Bump the minor-npm-dependencies group across 1 directory with 4
    updates by <a
    href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/1739">actions/checkout#1739</a></li>
    <li>Bump actions/checkout from 3 to 4 by <a
    href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/1697">actions/checkout#1697</a></li>
    <li>Check out other refs/* by commit by <a
    href="https://github.com/orhantoy"><code>@​orhantoy</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/1774">actions/checkout#1774</a></li>
    <li>Pin actions/checkout's own workflows to a known, good, stable
    version. by <a href="https://github.com/jww3"><code>@​jww3</code></a> in
    <a
    href="https://redirect.github.com/actions/checkout/pull/1776">actions/checkout#1776</a></li>
    </ul>
    <h2>v4.1.6</h2>
    <ul>
    <li>Check platform to set archive extension appropriately by <a
    href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in
    <a
    href="https://redirect.github.com/actions/checkout/pull/1732">actions/checkout#1732</a></li>
    </ul>
    <h2>v4.1.5</h2>
    <ul>
    <li>Update NPM dependencies by <a
    href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in
    <a
    href="https://redirect.github.com/actions/checkout/pull/1703">actions/checkout#1703</a></li>
    <li>Bump github/codeql-action from 2 to 3 by <a
    href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/1694">actions/checkout#1694</a></li>
    <li>Bump actions/setup-node from 1 to 4 by <a
    href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/1696">actions/checkout#1696</a></li>
    <li>Bump actions/upload-artifact from 2 to 4 by <a
    href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
    href="https://redirect.github.com/actions/checkout/pull/1695">actions/checkout#1695</a></li>
    </ul>
    <!-- raw HTML omitted -->
    </blockquote>
    <p>... (truncated)</p>
    </details>
    <details>
    <summary>Commits</summary>
    <ul>
    <li><a
    href="1af3b93b68"><code>1af3b93</code></a>
    update readme/changelog for v6 (<a
    href="https://redirect.github.com/actions/checkout/issues/2311">#2311</a>)</li>
    <li><a
    href="71cf2267d8"><code>71cf226</code></a>
    v6-beta (<a
    href="https://redirect.github.com/actions/checkout/issues/2298">#2298</a>)</li>
    <li><a
    href="069c695914"><code>069c695</code></a>
    Persist creds to a separate file (<a
    href="https://redirect.github.com/actions/checkout/issues/2286">#2286</a>)</li>
    <li><a
    href="ff7abcd0c3"><code>ff7abcd</code></a>
    Update README to include Node.js 24 support details and requirements (<a
    href="https://redirect.github.com/actions/checkout/issues/2248">#2248</a>)</li>
    <li><a
    href="08c6903cd8"><code>08c6903</code></a>
    Prepare v5.0.0 release (<a
    href="https://redirect.github.com/actions/checkout/issues/2238">#2238</a>)</li>
    <li><a
    href="9f265659d3"><code>9f26565</code></a>
    Update actions checkout to use node 24 (<a
    href="https://redirect.github.com/actions/checkout/issues/2226">#2226</a>)</li>
    <li><a
    href="08eba0b27e"><code>08eba0b</code></a>
    Prepare release v4.3.0 (<a
    href="https://redirect.github.com/actions/checkout/issues/2237">#2237</a>)</li>
    <li><a
    href="631c7dc4f8"><code>631c7dc</code></a>
    Update package dependencies (<a
    href="https://redirect.github.com/actions/checkout/issues/2236">#2236</a>)</li>
    <li><a
    href="8edcb1bdb4"><code>8edcb1b</code></a>
    Update CODEOWNERS for actions (<a
    href="https://redirect.github.com/actions/checkout/issues/2224">#2224</a>)</li>
    <li><a
    href="09d2acae67"><code>09d2aca</code></a>
    Update README.md (<a
    href="https://redirect.github.com/actions/checkout/issues/2194">#2194</a>)</li>
    <li>Additional commits viewable in <a
    href="https://github.com/actions/checkout/compare/v3...v6">compare
    view</a></li>
    </ul>
    </details>
    <br />

    [![Dependabot compatibility
    score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3&new-version=6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

    Dependabot will resolve any conflicts with this PR as long as you don't
    alter it yourself. You can also trigger a rebase manually by commenting
    `@dependabot rebase`.

    [//]: # (dependabot-automerge-start)
    [//]: # (dependabot-automerge-end)

    ---

    <details>
    <summary>Dependabot commands and options</summary>
    <br />

    You can trigger Dependabot actions by commenting on this PR:
    - `@dependabot rebase` will rebase this PR
    - `@dependabot recreate` will recreate this PR, overwriting any edits
    that have been made to it
    - `@dependabot merge` will merge this PR after your CI passes on it
    - `@dependabot squash and merge` will squash and merge this PR after
    your CI passes on it
    - `@dependabot cancel merge` will cancel a previously requested merge
    and block automerging
    - `@dependabot reopen` will reopen this PR if it is closed
    - `@dependabot close` will close this PR and stop Dependabot recreating
    it. You can achieve the same result by closing it manually
    - `@dependabot show <dependency name> ignore conditions` will show all
    of the ignore conditions of the specified dependency
    - `@dependabot ignore this major version` will close this PR and stop
    Dependabot creating any more for this major version (unless you reopen
    the PR or upgrade to it yourself)
    - `@dependabot ignore this minor version` will close this PR and stop
    Dependabot creating any more for this minor version (unless you reopen
    the PR or upgrade to it yourself)
    - `@dependabot ignore this dependency` will close this PR and stop
    Dependabot creating any more for this dependency (unless you reopen the
    PR or upgrade to it yourself)

    </details>

    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

commit 4d3c223402
Author: Jiří Polášek <me@jiripolasek.com>
Date:   Mon Dec 1 02:32:30 2025 +0100

    CmdPal: Fix grid views (#43991)

    ## Summary of the Pull Request

    This PR fixes the crash due to binding to a trimmed property. For this
    it converts runtime bindings on GridView to use `{x:Bind}` so this issue
    can't happen in the future.

    - Fixes a crash related to the `Visibility` property in gallery/grid
    views when trimmed during AOT builds.
    - Fixes ShowTitle and ShowSubtitle properties, they are now taken into
    account in a view.
    - Improves UI layout, removes some margins and maches the corner radius
    of the item contaienr with the item content in the gallery view.
    - Refactores gallery and grid views to move logic from the view to the
    view model so we can x:Bind to them.
    - Replaces `{Binding}` with `{x:Bind}` to improve performance and enable
    compile-time binding validation.
    - Properties related to grids are splatted on to the common
    `IGridPropertiesViewModel` interface. Subclassing would add extra
    overhead without substential benefit.
    - Adds new samples to showcase various grid view configurations.

    ## Pictures? Pictures!

    A) Gallery view (with title and subtitle)
    <img width="909" height="583" alt="image"
    src="https://github.com/user-attachments/assets/b807e7a8-412f-4817-8121-e3470c49e0c0"
    />

    B) Gallery view (only title)
    <img width="903" height="582" alt="image"
    src="https://github.com/user-attachments/assets/b619d63f-04d0-42f2-9207-de256dc5e481"
    />

    C) Gallery view (no title or subtitle)
    <img width="900" height="583" alt="image"
    src="https://github.com/user-attachments/assets/c48cd1fc-8f51-40c1-8bce-607916e9f742"
    />

    D) Small icons
    <img width="907" height="582" alt="image"
    src="https://github.com/user-attachments/assets/8327da0a-fa45-443f-b52c-f0f1edd7b861"
    />

    E) Medium icons (with labels)
    <img width="914" height="588" alt="image"
    src="https://github.com/user-attachments/assets/dee9fab1-54e8-45f8-96d7-502b121a6ac2"
    />

    F) Medium icons (no labels)
    <img width="915" height="588" alt="image"
    src="https://github.com/user-attachments/assets/a32e8af2-6cb1-4106-91db-ca396253c0a3"
    />

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes: #43973
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 1ba5a258e9
Author: Jiří Polášek <me@jiripolasek.com>
Date:   Sun Nov 30 01:59:58 2025 +0100

    CmdPal: Add custom search engine option to Web Search extension (#43941)

    ## Summary of the Pull Request

    This PR allows user to customize a search query in Command Palette's Web
    Search built-in extension. This will also solve a problem with some
    browser that doesn't handle argument in form "? <query>" as it will
    allow user to specify the complete URI.

    - Introduces a new text box in Web Search extension settings for
    specifying a custom search engine URI
    - If the text box is non-empty, the provided URI is used for queries
    - If left empty, the extension defaults to previous behavior, sending
    queries in the format "? query"

    ## Pictures? Pictures!

    <img width="825" height="566" alt="image"
    src="https://github.com/user-attachments/assets/fbf3d3a5-ebfe-4c16-a5f1-0d044b6f9047"
    />

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes: #43940
    - [x] Closes: #42867
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 8aea589b01
Author: Jiří Polášek <me@jiripolasek.com>
Date:   Sun Nov 30 00:36:55 2025 +0100

    CmdPal: Align spellchecker and naming to .NET guidelines (#43974)

    ## Summary of the Pull Request

    - Add command-line parameter value (icf)
    - Unify file and class name casing to match .NET naming conventions (RDP
    -> Rdp as Url, Dns, Xml) -- fixes IRDP spellchecking error
    - Rename IRdpConnectionManager to IRdpConnectionsManager (*s) to match
    the class name

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit afd9d4cc3c
Author: Clint Rutkas <clint@rutkas.com>
Date:   Sat Nov 29 15:11:17 2025 -0800

    Update PowerToys download links to version 0.96.1 (#43965)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit bc0a760aff
Author: Jiří Polášek <me@jiripolasek.com>
Date:   Sat Nov 29 23:23:24 2025 +0100

    CmdPal: Add mini dev center (#43939)

    ## Summary of the Pull Request

    This PR introduces a small ribbon to the CmdPal for app developers. The
    dev ribbon is dynamically added to the main window in local (non-CI)
    builds. It shows the number of logged errors and warnings, the current
    build configuration (Debug or Release), and whether it’s built with AOT.

    The flyout shows the latest errors and warnings and lets you quickly
    access the logs.

    ## Pictures? Pictures!

    <img width="985" height="589" alt="image"
    src="https://github.com/user-attachments/assets/6528b02b-b4b4-4968-91bf-e67a29f86415"
    />

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes: #43318
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 06afe09973
Author: Michael Jolley <mike@baldbeardedbuilder.com>
Date:   Sat Nov 29 13:07:19 2025 -0600

    CmdPal: New Remote Desktop built-in extension (#43090)

    This PR introduces a new built-in extension for Remote Desktop users.

    It allows you to view past RDP connections, save predefined connections,
    and connect to any of them. Or start a new RDP connection.

    https://github.com/user-attachments/assets/6a5041a6-5741-4df0-a305-da7166f962e1

    ### GitHub issue maintenance stuff

    Closes #38305

    ---------

    Co-authored-by: Niels Laute <niels.laute@live.nl>
    Co-authored-by: Jiří Polášek <me@jiripolasek.com>

commit 0de60445ea
Author: Jiří Polášek <me@jiripolasek.com>
Date:   Thu Nov 27 16:31:10 2025 +0100

    CmdPal: Use Shell API to determine the default browser in WebSearch (#43339)

    ## Summary of the Pull Request

    This PR introduces a new method for determining the default browser
    using the Windows Shell API. The new provider selects the browser
    associated with the HTTPS protocol (falling back to HTTP if necessary).
    The original implementation is retained as a fallback for now, and the
    codebase is prepared for future extensions (e.g., manual default-browser
    selection).

    As a flyby, it also fixes an issue where commands continued showing the
    previous browser name if the user changed their default browser while
    the Command Palette was running.

    ## One-liner for change log

    Fixed default browser selection in the Web Search built-in extension.

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes: #42343
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [x] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 47d4a65223
Author: Jiří Polášek <me@jiripolasek.com>
Date:   Thu Nov 27 16:24:47 2025 +0100

    CmdPal: Add option to return to home automatically after a delay (#43551)

    ## Summary of the Pull Request

    This PR replaces the Go home when activated setting with a new
    Automatically return home option. This allows users to specify how long
    the Command Palette should wait after being dismissed before
    automatically returning to the home page. It also introduces migration
    logic to transition from the old setting to the new one.

    ## Pictures? Pictures!

    <img width="1337" height="762" alt="image"
    src="https://github.com/user-attachments/assets/c649ef03-b3ee-40ba-ac67-485bc40efa73"
    />

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes: #43355
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 1b72c0b969
Author: Kai Tao <69313318+vanzue@users.noreply.github.com>
Date:   Thu Nov 27 17:22:59 2025 +0800

    Update check-spelling expect list (#43925)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

    Spell no complain

commit 9160c82fc2
Author: Pratyush Nalam <github@code.pratyushnalam.com>
Date:   Thu Nov 27 05:15:06 2025 +0530

    Update Command Palette's Learn More string to be consistent with other utilities (#43898)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request

    In the PowerToys "What's new" window, every utility has the text "Learn
    more about <utility name>" next to the "Settings" button. Examples
    below:

    <img width="247" height="38" alt="learnmore-fancyzones"
    src="https://github.com/user-attachments/assets/fecdeb4b-e01c-438d-8d11-c056e613768e"
    />
    <img width="258" height="40" alt="learnmore-textextractor"
    src="https://github.com/user-attachments/assets/ffb0c801-5b89-46d1-b493-b57287303e65"
    />

    The only exception is the Command Palette utility which just says "Learn
    more".

    <img width="152" height="32" alt="learnmore-cmdpal"
    src="https://github.com/user-attachments/assets/232c11cd-b621-46eb-87f1-d3fc708d6286"
    />

    This is an inconsistency and this PR fixes that string.

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes: #43897
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 452e0dcf51
Author: Mike Hall <mikehall@microsoft.com>
Date:   Wed Nov 26 14:08:34 2025 +0000

    Module Loader tool for rapid testing of modules (#43813)

    ## Summary of the Pull Request
    ModuleLoader tool, a stand-alone Win32 executable for testing of
    PowerToy modules without needing branch builds.

    sample output from running the tool is below:

    .\ModuleLoader.exe .\powertoys.cursorwrap.dll
    PowerToys Module Loader v1.0
    =============================

    Loading module: .\powertoys.cursorwrap.dll
    Detected module name: cursorwrap

    Loading settings...
    Trying settings path:
    C:\Users\mikehall\AppData\Local\Microsoft\PowerToys\cursorwrap\settings.json
    Settings file loaded (315 characters)
    Settings loaded successfully.

    Loading module DLL...
    Module instance created successfully
    Module DLL loaded successfully.
    Module key: CursorWrap
    Module name: CursorWrap

    Applying settings to module...
    Settings applied.

    Registering module hotkeys...
    Module reports 1 legacy hotkey(s)
      Registering hotkey 0: Win+Alt+U - OK
    Hotkeys registered: 1

    Enabling module...
    Module enabled.

    =============================
    Module is now running!
    =============================

    Module Status:
      - Name: CursorWrap
      - Key: CursorWrap
      - Enabled: Yes
      - Hotkeys: 1 registered

    Registered Hotkeys:
      Win+Alt+U

    Press Ctrl+C to exit.
    You can press the module's hotkey to toggle its functionality.

    Note that this doesn't integrate with Powertoys settings UI - this is
    purely to test Powertoys module functionality.

    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    ## Detailed Description of the Pull Request / Additional comments
    See details above.

    ## Validation Steps Performed
    ModuleLoader tested on Windows 11, Surface Laptop 7 Pro.

commit 2c9a9e9fca
Author: Jiří Polášek <me@jiripolasek.com>
Date:   Mon Nov 24 23:57:10 2025 +0100

    CmdPal: Improve Command Palette behavior in "Last position" mode (#43543)

    ## Summary of the Pull Request

    This PR improves Command Palette behavior in “Last position” mode:
    - Correctly handles DPI changes between monitors.
    - Ensures the window is always visible — if it’s fully off-screen or has
    less than 100px visible on any axis, it is re-centered.

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes: #43398
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 09c8c1d79a
Author: leileizhang <leilzh@microsoft.com>
Date:   Mon Nov 24 10:42:35 2025 +0800

    [Hot Fix] Fix Image Resizer not working on Win10 (#43763)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request
    Windows 10 can’t launch the app using the Sparse Package. Remove the app
    manifest so that Image Resizer can start properly on Windows 10.

    We will figure out how to support Sparse Packages on Windows 10 in the
    next release.
    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes: #43747 #43734 #43722 #43759
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 95c8a83f79
Author: leileizhang <leilzh@microsoft.com>
Date:   Mon Nov 24 10:08:12 2025 +0800

    [Hotfix] Remove the properties in Prompt Execution Settings for OpenAI (#43766)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request
    Remove the properties in Prompt Execution Settings for OpenAI, as the
    new models may not support them.

    Will try to expose them in the UI so users can add them on their own in
    the next release.

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist
    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 2830ea919c
Author: Kai Tao <69313318+vanzue@users.noreply.github.com>
Date:   Mon Nov 24 09:51:27 2025 +0800

    Advanced Paste: Adjust model parameter to make the result longer (#43768)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request
    Adjust model parameter to make the result longer
    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 725ad21952
Author: Dave Rayment <dave.rayment@gmail.com>
Date:   Mon Nov 24 01:12:54 2025 +0000

    [Awake] Fix issue with timed mode not expiring correctly (#43785)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request
    Resolves an issue with the timed mode's expiry not completing correctly.

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes: #43775
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments
    This was because of my recent change to the timed mode. The `Subscribe`
    method on the `Observable` interval accidentally wired the completion
    logic to the **Error** handler instead of the **Completion** handler
    because of the use of a discard `_` instead of an empty parameter list
    `()`. As a result of the incorrect overload being called, Awake stayed
    in the Timed state despite the timer reaching zero.

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed
    Confirmed that the timed mode times out and exits upon expiry.

commit ebc3a139c5
Author: Erik Anderson <erik.anderson@microsoft.com>
Date:   Fri Nov 21 02:34:34 2025 -0800

    Fix typo in AI settings card description (#43757)

    ## Summary of the Pull Request
    The word "cloud" does not use a vowel sound, so the preceding word
    should be "A" instead of "An".

    ## PR Checklist

    - [X] Closes: #43756
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [X] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    Co-authored-by: Erik Anderson <erikan@ntdev.microsoft.com>

commit 28dba2633e
Author: Jaylyn Barbee <51131738+Jaylyn-Barbee@users.noreply.github.com>
Date:   Thu Nov 20 15:22:40 2025 -0800

    [Light Switch][Dev Docs] Clarify LightSwitchService and LightSwitchStateManager roles (#43748)

    Updated LightSwitch module documentation to clarify the role of
    LightSwitchService and LightSwitchStateManager.

    ---------

    Co-authored-by: Niels Laute <niels.laute@live.nl>

commit 9fbd3de3a2
Author: Jiří Polášek <me@jiripolasek.com>
Date:   Thu Nov 20 16:23:42 2025 +0100

    CmdPal: Add native debugging launch profile to launchSettings.json (#43718)

    ## Summary of the Pull Request

    See title.

    I’m too lazy to open the dialog and then revert the change later.

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 4a0d9912ae
Author: Kai Tao <69313318+vanzue@users.noreply.github.com>
Date:   Thu Nov 20 09:57:29 2025 +0800

    Advanced Paste:  No cache for foundry local model list  (#43716)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request
    Cache of the downloaded model will make the newly added model only work
    after running of powertoys, this disable the cache, so just downloaded
    model will take effect immediately

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed
    Validated locally

commit 15c79a0176
Author: Dave Rayment <dave.rayment@gmail.com>
Date:   Wed Nov 19 08:50:25 2025 +0000

    [Settings] Fix inconsistent description text for the mouse tools (#43651)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request
    Change some of the mouse utilities' descriptions from declarative to
    imperative, to match best practice and to be consistent with the other
    descriptions.

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed
    - Confirmed the changed descriptions were updated in Settings.

commit 97d46efec2
Author: Dave Rayment <dave.rayment@gmail.com>
Date:   Wed Nov 19 08:49:40 2025 +0000

    [Settings] Fix Dashboard toggle glitches and sorting UI (#43626)

    ## Summary of the Pull Request
    Fixes two UI bugs in the Settings Dashboard: module list glitching when
    toggling modules, and incorrect sort menu checkmarks.

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes: #43624
    - [x] Closes: #43625
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    ### User-Facing Fixes

    #### 1. Module list glitching when toggling enabled state
    When enabling or disabling a module from the "Utilities" list, the
    entire list would flicker and redraw, causing other toggles to glitch.
    This made it appear as if multiple modules were being affected by a
    single change.

    **Root cause**
    The `AllModules` ObservableCollection was being completely cleared and
    re-populated on every change, forcing the UI to destroy and recreate all
    list items.

    **Fix**
    Refactored collection updates to modify items in-place:
    - Introduced `_moduleItems` master list, built once during
    initialization.
    - `RefreshModuleList()` now updates properties without clearing
    collections
    - `SortModuleList()` uses `ObservableCollection.Move()` instead of
    `Clear()`/`Add()`

    #### 2. Incorrect sort menu checkmark behaviour
    The checkmark in the "Sort by" menu would not update correctly when
    changing sort order, sometimes showing the incorrect item checked, or
    even both at once.

    **Root cause**
    The `IsChecked` prop on the `ToggleMenuFlyoutItem` is bound to
    `DashboardSortOrder`, but the binding was not updating because the
    ViewModel didn't raise a property change notification when the sort
    order was changed.

    **Fix**
    Added `OnPropertyChanged(nameof(DashboardSortOrder))` in
    `SortModuleList()`.

    ### Code quality improvements

    1. Renamed `GetShortcutModules()` to `RefreshShortcutModules()`. The
    original name implied a getter, but the routine actually affects state
    by rebuilding the shortcut and action lists, violating the Command-Query
    Separation principle.
    2. Added an `_isUpdatingFromUI` flag as a defensive measure against
    circular updates when a UI toggle is changed.
    3. Separation of concerns for operations on the modules list. Building,
    sorting and refreshing it are separated.
    4. Added comments and XML doc headers for new methods. Included brief
    description of GPO locking behaviour.

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed
    - Verified that toggling modules in the list no longer causes the list
    to flicker or for other toggles to glitch.
    - Confirmed that the sort order checkmarks update correctly and reflect
    the current sort order.
    - Tested GPO policy settings are still queried as before.
    - Checked sort behaviour is unaffected.

    ## Videos

    *Sorting UI*

    https://github.com/user-attachments/assets/3484bf63-2946-4460-83a5-361fa7e41c82

    *Toggle behaviour*

    https://github.com/user-attachments/assets/1fae5429-6fa3-4431-80f3-0907dab4f326

    ---------

    Co-authored-by: Gordon Lam (SH) <yeelam@microsoft.com>

commit 46242b384e
Author: Kai Tao <69313318+vanzue@users.noreply.github.com>
Date:   Wed Nov 19 16:25:52 2025 +0800

    96 release change log (#43330)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

    ---------

    Signed-off-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com>
    Signed-off-by: Shawn Yuan <shuai.yuan.zju@gmail.com>
    Co-authored-by: Jiří Polášek <me@jiripolasek.com>
    Co-authored-by: Jaylyn Barbee <51131738+Jaylyn-Barbee@users.noreply.github.com>
    Co-authored-by: Jeremy Sinclair <4016293+snickler@users.noreply.github.com>
    Co-authored-by: leileizhang <leilzh@microsoft.com>
    Co-authored-by: Shawn Yuan <128874481+shuaiyuanxx@users.noreply.github.com>
    Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
    Co-authored-by: niels9001 <9866362+niels9001@users.noreply.github.com>
    Co-authored-by: Niels Laute <niels.laute@live.nl>
    Co-authored-by: Dave Rayment <dave.rayment@gmail.com>
    Co-authored-by: Gleb Khmyznikov <gleb.khmyznikov@gmail.com>
    Co-authored-by: Gordon Lam (SH) <yeelam@microsoft.com>
    Co-authored-by: Juju Anselum J <106316316+anselumjuju@users.noreply.github.com>
    Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
    Co-authored-by: Leon Zandman <leon@wirwar.com>
    Co-authored-by: Leon Zandman <lzandman@rdw.nl>
    Co-authored-by: moooyo <42196638+moooyo@users.noreply.github.com>
    Co-authored-by: Yu Leng <yuleng@microsoft.com>
    Co-authored-by: Mike Griese <migrie@microsoft.com>
    Co-authored-by: Michael Jolley <mike@baldbeardedbuilder.com>
    Co-authored-by: Mario Hewardt <marioh@microsoft.com>
    Co-authored-by: Alex Mihaiuc <69110671+foxmsft@users.noreply.github.com>
    Co-authored-by: Mike Hall <mikehall@microsoft.com>
    Co-authored-by: Trevor <ngo.trev.95@gmail.com>

commit 84be261581
Author: Niels Laute <niels.laute@live.nl>
Date:   Tue Nov 18 19:19:38 2025 -0800

    Logo change for Azure Inference (#43686)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 5a8095b704
Author: Niels Laute <niels.laute@live.nl>
Date:   Tue Nov 18 18:32:14 2025 -0800

    Loc bug (#43685)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 417c1a6b98
Author: Niels Laute <niels.laute@live.nl>
Date:   Tue Nov 18 16:21:14 2025 -0800

    Update FoundryLocal.svg (#43682)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 2593149d22
Author: leileizhang <leilzh@microsoft.com>
Date:   Tue Nov 18 14:22:03 2025 +0800

    Fix OOBE Mouse Utilities crash by correcting localization key (#43664)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request

    - The OOBE Mouse Utilities page crashed when selected because the
    TextBlock with x:Uid="Oobe_MouseUtils_MousePointerCrosshairs" tried to
    bind a Description property that doesn’t exist.
    - Updated Resources.resw so the string entry is named
    Oobe_MouseUtils_MousePointerCrosshairs_Description.Text, matching the
    markdown description control instead of the TextBlock.
    - With the correct resource key, the XAML loader no longer resolves an
    invalid property and navigation succeeds.

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes:  #43663
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 0b50c38fe1
Author: Kai Tao <69313318+vanzue@users.noreply.github.com>
Date:   Tue Nov 18 12:59:52 2025 +0800

    Advanced Paste: Refresh environment if foundry is not present (#43662)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request
    As title
    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

    [12:55:29.6763496] [Info] FoundryClient.cs::CreateAsync::23
        [FoundryClient] First attempt failed, refreshing PATH and retrying
    [12:55:29.6766491] [Info] FoundryClient.cs::RefreshEnvironmentPath::225
        [FoundryClient] Refreshing PATH environment variable from system
    [12:55:29.6768710] [Info] FoundryClient.cs::RefreshEnvironmentPath::266
        [FoundryClient] Updating process PATH with latest system values
    [12:55:29.6769080] [Info] FoundryClient.cs::TryCreateClientAsync::33
        [FoundryClient] Creating Foundry Local client
    [12:55:29.6769312] [Info] FoundryClient.cs::TryCreateClientAsync::45
    [FoundryClient] Starting Foundry service using
    manager.StartServiceAsync()
    [12:55:29.9807668] [Info] FoundryClient.cs::TryCreateClientAsync::48
        [FoundryClient] Foundry service started successfully

    Verified, fist launch successfully

commit 840808b465
Author: Niels Laute <niels.laute@live.nl>
Date:   Tue Nov 18 03:28:40 2025 +0100

    [AP] Adding a single scrollviewer and fixing hidden tabstop (#43660)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes: #43655
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit b50df36b70
Author: Jiří Polášek <me@jiripolasek.com>
Date:   Tue Nov 18 03:00:37 2025 +0100

    Setup: Hide apps in PowerToys.SpareApps package from Start Menu (#43650)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request

    This PR updates the Appx manifest for PowerToys.SpareApps to hide the
    apps from the Start Menu, as they lack proper visual elements like icons
    and text.

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [x] Closes: #43647
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit b94593ef73
Author: Jiří Polášek <me@jiripolasek.com>
Date:   Tue Nov 18 00:55:14 2025 +0100

    Settings: Add ScrollViewer to Command Palette page in PowerToys Settings (#43649)

commit 7a01d56179
Author: Mario Hewardt <marioh@microsoft.com>
Date:   Mon Nov 17 07:26:42 2025 -0800

    Updates version for standalone release (#43645)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request
    Updates the version for standalone release

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 130e9a0a68
Author: Kai Tao <69313318+vanzue@users.noreply.github.com>
Date:   Mon Nov 17 12:55:22 2025 +0800

    cmdpal: Fix launch by button in settings not work (#43634)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request
    Shell does not know it's a protocol, so add protocol to it.

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed
    Locally verified

commit 34c37f2d38
Author: Kai Tao <69313318+vanzue@users.noreply.github.com>
Date:   Mon Nov 17 09:48:32 2025 +0800

    Add not signed dll (#43631)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request

    This dll is not signed, will fail the pipeline

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 47aed03c03
Author: Niels Laute <niels.laute@live.nl>
Date:   Sun Nov 16 15:13:40 2025 +0100

    [AP] Loc fix (#43617)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 6423c7693d
Author: Niels Laute <niels.laute@live.nl>
Date:   Sun Nov 16 15:02:38 2025 +0100

    [CmdPal] Settings page refresh (#43487)

    - Refreshed the CmdPal page.
    - CmdPal can now also be activated from this page by clicking a button
    - Added a Preview InfoBar for FL in AP

    <img width="1384" height="1067" alt="image"
    src="https://github.com/user-attachments/assets/f670e13b-5b4a-4f6a-bcb0-e1dc357afb1e"
    />

    ## Summary of the Pull Request

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

    ---------

    Co-authored-by: vanzue <vanzue@outlook.com>

commit 3e14d50f65
Author: Kai Tao <69313318+vanzue@users.noreply.github.com>
Date:   Sun Nov 16 15:26:05 2025 +0800

    Advanced paste: Add more error handle for foundry local (#43600)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request
    Foundry local sdk will not run models that is not in catalog, when
    catalog removes some, the old ones will fail executing,
    so add error hint for users to re-configure the models in settings.

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed
    <img width="864" height="216" alt="image"
    src="https://github.com/user-attachments/assets/654207b3-ff50-4888-a638-82136216de7b"
    />

commit db7c9e180e
Author: Jaylyn Barbee <51131738+Jaylyn-Barbee@users.noreply.github.com>
Date:   Sat Nov 15 08:08:20 2025 -0500

    [Light Switch] Removed logs from every tick, only logging key events. (#43572)

    Title

commit bcc3ded280
Author: Michael Jolley <mike@baldbeardedbuilder.com>
Date:   Sat Nov 15 07:07:52 2025 -0600

    CmdPal: Adding page Id to OpenPage telemetry event (#43584)

    @niels9001 requested this.

    As the name says

commit 24a3cdd486
Author: Mario Hewardt <marioh@microsoft.com>
Date:   Fri Nov 14 17:36:31 2025 -0800

    Fixes regressions introduced with GIF support (#43589)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Fixes regressions introduced with GIF support:
    - Switches default recording format back to MP4
    - Fixes framerate issues between the two formats
    - Fixes file path names

    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [x ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments
    - Switches default recording format back to MP4
    - Fixes framerate issues between the two formats
    - Fixes file path names
    -
    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed
    Manual testing

commit 1884e6abc1
Author: Shawn Yuan <128874481+shuaiyuanxx@users.noreply.github.com>
Date:   Fri Nov 14 16:56:23 2025 +0800

    Remove unused properties in AP (#43564)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request
    This pull request removes legacy provider configuration migration logic
    and associated data structures from the Advanced Paste AI provider
    settings. The changes simplify the codebase by eliminating support for
    legacy provider configuration snapshots and related migration methods,
    focusing configuration management on the current provider model.

    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

    ---------

    Signed-off-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com>

commit ad4b553bb1
Author: leileizhang <leilzh@microsoft.com>
Date:   Fri Nov 14 16:15:15 2025 +0800

    Remove all AdvancedPaste stored keys during uninstall (#43563)

    <!-- Enter a brief description/summary of your PR here. What does it
    fix/what does it change/how was it tested (even manually, if necessary)?
    -->
    ## Summary of the Pull Request
    Remove all AdvancedPaste stored keys during uninstall
    <!-- Please review the items on the PR checklist before submitting-->
    ## PR Checklist

    - [ ] Closes: #xxx
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved
    issues) -->
    - [ ] **Communication:** I've discussed this with core contributors
    already. If the work hasn't been agreed, this work might be rejected
    - [ ] **Tests:** Added/updated and all pass
    - [ ] **Localization:** All end-user-facing strings can be localized
    - [ ] **Dev docs:** Added/updated
    - [ ] **New binaries:** Added on the required places
    - [ ] [JSON for
    signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
    for new binaries
    - [ ] [WXS for
    installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
    for new binaries and localization folder
    - [ ] [YML for CI
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
    for new test projects
    - [ ] [YML for signed
    pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
    - [ ] **Documentation updated:** If checked, please file a pull request
    on [our docs
    repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
    and link it here: #xxx

    <!-- Provide a more detailed description of the PR, other things fixed,
    or any additional comments/features here -->
    ## Detailed Description of the Pull Request / Additional comments

    <!-- Describe how you validated the behavior. Add automated tests
    wherever possible, but list manual validation steps taken as well -->
    ## Validation Steps Performed

commit 193d9aacbe
Author: Dustin L. Howett <duhowett@microsoft.com>
Date:   Thu Nov 13 17:59:21 2025 -0600

    BugReportTool: replace cziplib with tar.exe (#41127)

    BugReportTool is the last consumer in the PowerToys repo of cziplib, a
    library we use to produce ZIP files.

    This pull request replaces cziplib with a simple CreateProcess call that
    spawns `tar.exe`, which comes with Windows as of RS4 and can produce ZIP
    files!

    I've tested this by producing a bug report archive and attempting to
    open it with File Explorer. It works fine.

    We have taken every precaution to ensure that we do not allow any
    attacker-controlled input to tar's command line. We are *not* using
    `system()`, and we are not opening up a vector through which a nefarious
    caller can perform shell injection.

    We do not pass filenames to tar except that of the final archive. We do
    not pass directory names to tar; we rely on the current directory
    instead.
This commit is contained in:
Gleb Khmyznikov
2025-12-08 18:41:48 -08:00
parent ae512c9cbc
commit a5b9cc77ec
276 changed files with 7066 additions and 5884 deletions

View File

@@ -95,6 +95,7 @@ OTP
Yubi
Yubico
Perplexity
Groq
svgl
# KEYS
@@ -328,3 +329,9 @@ FFF
HHH
riday
YYY
# GitHub issue/PR commands
azp
feedbackhub
needinfo
reportbug

View File

@@ -221,6 +221,7 @@ clientside
CLIPBOARDUPDATE
CLIPCHILDREN
CLIPSIBLINGS
CLITo
closesocket
clp
CLSCTX
@@ -728,9 +729,9 @@ HWNDPARENT
HWNDPREV
hyjiacan
IAI
icf
ICONERROR
ICONLOCATION
icf
IDCANCEL
IDD
idk
@@ -773,6 +774,7 @@ INITGUID
INITTOLOGFONTSTRUCT
INLINEPREFIX
inlines
Inno
INPC
inproc
INPUTHARDWARE
@@ -1072,6 +1074,7 @@ MVVMTK
MWBEx
MYICON
NAMECHANGE
Notavailable
namespaceanddescendants
nao
NCACTIVATE
@@ -1480,6 +1483,7 @@ rgh
rgn
rgs
rguid
rhk
RIDEV
RIGHTSCROLLBAR
riid
@@ -1585,6 +1589,7 @@ SHGDNF
SHGFI
SHIL
shinfo
shk
shlwapi
shobjidl
SHORTCUTATLEAST
@@ -1629,6 +1634,7 @@ SKIPOWNPROCESS
sku
SLGP
sln
slnx
SMALLICON
smartphone
smileys
@@ -1794,6 +1800,7 @@ tlbimp
tlc
tmain
TNP
toolgood
Toolhelp
toolwindow
TOPDOWNDIB
@@ -1847,6 +1854,7 @@ UNCPRIORITY
UNDNAME
UNICODETEXT
unins
Uninstaller
uninstalls
Uniquifies
unitconverter

View File

@@ -60,6 +60,8 @@
"PowerToys.FancyZonesEditorCommon.dll",
"PowerToys.FancyZonesModuleInterface.dll",
"PowerToys.FancyZones.exe",
"FancyZonesCLI.exe",
"FancyZonesCLI.dll",
"PowerToys.GcodePreviewHandler.dll",
"PowerToys.GcodePreviewHandler.exe",

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.PowerToys.Telemetry" version="2.0.3" />
<package id="Microsoft.PowerToys.Telemetry" version="2.0.4" />
</packages>

View File

@@ -192,14 +192,14 @@ jobs:
displayName: Verify XAML formatting
- pwsh: |-
& '.pipelines/verifyNugetPackages.ps1' -solution '$(build.sourcesdirectory)\PowerToys.sln'
displayName: Verify Nuget package versions for PowerToys.sln
& '.pipelines/verifyNugetPackages.ps1' -solution '$(build.sourcesdirectory)\PowerToys.slnx'
displayName: Verify Nuget package versions for PowerToys.slnx
- pwsh: |-
& '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\PowerToys.sln'
& '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\PowerToys.slnx'
& '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\tools\BugReportTool\BugReportTool.sln'
& '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\tools\StylesReportTool\StylesReportTool.sln'
& '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\installer\PowerToysSetup.sln'
& '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\installer\PowerToysSetup.slnx'
displayName: Verify ARM64 configurations
- ${{ if eq(parameters.enablePackageCaching, true) }}:
@@ -252,7 +252,7 @@ jobs:
${{ else }}:
displayName: Build PowerToys main project
inputs:
solution: 'PowerToys.sln'
solution: 'PowerToys.slnx'
vsVersion: 17.0
msbuildArgs: >-
-restore -graph
@@ -275,7 +275,7 @@ jobs:
displayName: Generate DSC artifacts for ARM64
condition: and(succeeded(), eq(variables['BuildPlatform'], 'arm64'))
inputs:
solution: PowerToys.sln
solution: PowerToys.slnx
vsVersion: 17.0
msbuildArgs: >-
-restore

View File

@@ -74,7 +74,7 @@ jobs:
command: restore
feedsToUse: config
configPath: nuget.config
restoreSolution: PowerToys.sln
restoreSolution: PowerToys.slnx
restoreDirectory: '$(Build.SourcesDirectory)\packages'
# Build all UI test projects if no specific modules are specified
@@ -129,4 +129,4 @@ jobs:
- publish: $(JobOutputDirectory)
artifact: $(JobOutputArtifactName)
displayName: Publish UI Test artifacts
condition: always()
condition: always()

View File

@@ -35,7 +35,7 @@ steps:
- task: VSBuild@1
displayName: Build Shared Support DLLs
inputs:
solution: "**/installer/PowerToysSetup.sln"
solution: "**/installer/PowerToysSetup.slnx"
vsVersion: 17.0
msbuildArgs: >-
/t:PowerToysSetupCustomActionsVNext;SilentFilesInUseBAFunction
@@ -74,7 +74,7 @@ steps:
- task: VSBuild@1
displayName: 💻 Build VNext MSI
inputs:
solution: "**/installer/PowerToysSetup.sln"
solution: "**/installer/PowerToysSetup.slnx"
vsVersion: 17.0
msbuildArgs: >-
-restore
@@ -91,7 +91,7 @@ steps:
- task: VSBuild@1
displayName: 👤 Build VNext MSI
inputs:
solution: "**/installer/PowerToysSetup.sln"
solution: "**/installer/PowerToysSetup.slnx"
vsVersion: 17.0
msbuildArgs: >-
/t:PowerToysInstallerVNext
@@ -142,7 +142,7 @@ steps:
- task: VSBuild@1
displayName: 💻 Build VNext Bootstrapper
inputs:
solution: "**/installer/PowerToysSetup.sln"
solution: "**/installer/PowerToysSetup.slnx"
vsVersion: 17.0
msbuildArgs: >-
-restore
@@ -159,7 +159,7 @@ steps:
- task: VSBuild@1
displayName: 👤 Build VNext Bootstrapper
inputs:
solution: "**/installer/PowerToysSetup.sln"
solution: "**/installer/PowerToysSetup.slnx"
vsVersion: 17.0
msbuildArgs: >-
/t:PowerToysBootstrapperVNext

View File

@@ -54,4 +54,13 @@ steps:
feedsToUse: 'config'
nugetConfigPath: '$(build.sourcesdirectory)\nuget.config'
restoreSolution: '$(build.sourcesdirectory)\**\*.sln'
includeNuGetOrg: false
includeNuGetOrg: false
- task: NuGetCommand@2
displayName: 'Restore NuGet packages (slnx)'
inputs:
command: 'restore'
feedsToUse: 'config'
nugetConfigPath: '$(build.sourcesdirectory)\nuget.config'
restoreSolution: '$(build.sourcesdirectory)\**\*.slnx'
includeNuGetOrg: false

View File

@@ -42,6 +42,11 @@
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<!-- Make angle-bracket includes external and turn off code analysis for them -->
<TreatAngleIncludeAsExternal>true</TreatAngleIncludeAsExternal>
<ExternalWarningLevel>TurnOffAllWarnings</ExternalWarningLevel>
<DisableAnalyzeExternal>true</DisableAnalyzeExternal>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<PrecompiledHeader Condition="'$(UsePrecompiledHeaders)' != 'false'">Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
@@ -111,13 +116,11 @@
</PropertyGroup>
<!-- Debug/Release props -->
<PropertyGroup Condition="'$(Configuration)'=='Debug'"
Label="Configuration">
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'"
Label="Configuration">
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<LinkIncremental>false</LinkIncremental>

View File

@@ -243,6 +243,10 @@ _If you want to find diagnostic data events in the source code, these two links
<th>Event Name</th>
<th>Description</th>
</tr>
<tr>
<td>Microsoft.PowerToys.CmdNotFound_EnableCmdNotFound</td>
<td>Triggered when Command Not Found is enabled or disabled.</td>
</tr>
<tr>
<td>Microsoft.PowerToys.CmdNotFoundInstallEvent</td>
<td>Triggered when a Command Not Found is installed.</td>
@@ -257,6 +261,62 @@ _If you want to find diagnostic data events in the source code, these two links
</tr>
</table>
### Command Palette
<table style="width:100%">
<tr>
<th>Event Name</th>
<th>Description</th>
</tr>
<tr>
<td>Microsoft.PowerToys.CmdPal_BeginInvoke</td>
<td>Triggered when the Command Palette is launched by the user.</td>
</tr>
<tr>
<td>Microsoft.PowerToys.CmdPal_ColdLaunch</td>
<td>Occurs when Command Palette starts for the first time (cold start).</td>
</tr>
<tr>
<td>Microsoft.PowerToys.CmdPal_OpenPage</td>
<td>Triggered when a page is opened within the Command Palette, tracking navigation depth.</td>
</tr>
<tr>
<td>Microsoft.PowerToys.CmdPal_OpenUri</td>
<td>Occurs when a URI is opened through the Command Palette, including whether it's a web URL.</td>
</tr>
<tr>
<td>Microsoft.PowerToys.CmdPal_ReactivateInstance</td>
<td>Triggered when an existing Command Palette instance is reactivated.</td>
</tr>
<tr>
<td>Microsoft.PowerToys.CmdPal_RunCommand</td>
<td>Logs when a command is executed through the Command Palette, including admin elevation status.</td>
</tr>
<tr>
<td>Microsoft.PowerToys.CmdPal_RunQuery</td>
<td>Triggered when a search query is performed, including result count and duration.</td>
</tr>
<tr>
<td>Microsoft.PowerToys.CmdPalDismissedOnEsc</td>
<td>Occurs when the Command Palette is dismissed by pressing the Escape key.</td>
</tr>
<tr>
<td>Microsoft.PowerToys.CmdPalDismissedOnLostFocus</td>
<td>Triggered when the Command Palette is dismissed due to losing focus.</td>
</tr>
<tr>
<td>Microsoft.PowerToys.CmdPalHotkeySummoned</td>
<td>Logs when the Command Palette is summoned via hotkey, distinguishing between global and context-specific hotkeys.</td>
</tr>
<tr>
<td>Microsoft.PowerToys.CmdPalInvokeResult</td>
<td>Records the result type of a Command Palette invocation.</td>
</tr>
<tr>
<td>Microsoft.PowerToys.CmdPalProcessStarted</td>
<td>Triggered when the Command Palette process is started.</td>
</tr>
</table>
### Crop And Lock
<table style="width:100%">
<tr>
@@ -735,6 +795,10 @@ _If you want to find diagnostic data events in the source code, these two links
<th>Event Name</th>
<th>Description</th>
</tr>
<tr>
<td>Microsoft.PowerToys.NewPlus_ChangedTemplateLocation</td>
<td>Triggered when the template folder location is changed.</td>
</tr>
<tr>
<td>Microsoft.PowerToys.NewPlus_EventCopyTemplate</td>
<td>Triggered when an item from New+ is created (copied to the current directory).</td>
@@ -743,6 +807,10 @@ _If you want to find diagnostic data events in the source code, these two links
<td>Microsoft.PowerToys.NewPlus_EventCopyTemplateResult</td>
<td>Logs the success of item creation (copying).</td>
</tr>
<tr>
<td>Microsoft.PowerToys.NewPlus_EventOpenTemplates</td>
<td>Triggered when the templates folder is opened.</td>
</tr>
<tr>
<td>Microsoft.PowerToys.NewPlus_EventShowTemplateItems</td>
<td>Triggered when the New+ context menu flyout is displayed.</td>
@@ -928,12 +996,8 @@ _If you want to find diagnostic data events in the source code, these two links
<th>Description</th>
</tr>
<tr>
<td>Microsoft.PowerToys.ShortcutGuide_EnableGuide</td>
<td>Triggered when Shortcut Guide is enabled.</td>
</tr>
<tr>
<td>Microsoft.PowerToys.ShortcutGuide_HideGuide</td>
<td>Occurs when Shortcut Guide is hidden from view.</td>
<td>Microsoft.PowerToys.ShortcutGuide_GuideSession</td>
<td>Logs a Shortcut Guide session including duration and how it was closed.</td>
</tr>
<tr>
<td>Microsoft.PowerToys.ShortcutGuide_Settings</td>

View File

@@ -7,6 +7,8 @@
<PackageVersion Include="AdaptiveCards.ObjectModel.WinUI3" Version="2.0.0-beta" />
<PackageVersion Include="AdaptiveCards.Rendering.WinUI3" Version="2.1.0-beta" />
<PackageVersion Include="AdaptiveCards.Templating" Version="2.0.5" />
<PackageVersion Include="boost" Version="1.87.0" TargetFramework="native" />
<PackageVersion Include="boost_regex-vc143" Version="1.87.0" TargetFramework="native" />
<PackageVersion Include="CommunityToolkit.Labs.WinUI.Controls.OpacityMaskView" Version="0.1.251101-build.2372" />
<PackageVersion Include="Microsoft.Bot.AdaptiveExpressions.Core" Version="4.23.0" />
<PackageVersion Include="Appium.WebDriver" Version="4.4.5" />
@@ -69,10 +71,12 @@
This is present due to a bug in CsWinRT where WPF projects cause the analyzer to fail.
-->
<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />
<PackageVersion Include="Microsoft.Windows.ImplementationLibrary" Version="1.0.231216.1"/>
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.6901" />
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.8.250907003" />
<PackageVersion Include="Microsoft.WindowsAppSDK.AI" Version="1.8.37" />
<PackageVersion Include="Microsoft.WindowsAppSDK.Runtime" Version="1.8.250907003" />
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.8.251106002" />
<PackageVersion Include="Microsoft.WindowsAppSDK.Foundation" Version="1.8.251104000" />
<PackageVersion Include="Microsoft.WindowsAppSDK.AI" Version="1.8.39" />
<PackageVersion Include="Microsoft.WindowsAppSDK.Runtime" Version="1.8.251106002" />
<PackageVersion Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.9" />
<PackageVersion Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.39" />
<PackageVersion Include="ModernWpfUI" Version="0.9.4" />
@@ -111,6 +115,7 @@
<PackageVersion Include="System.IO.Abstractions.TestingHelpers" Version="22.0.13" />
<PackageVersion Include="System.Management" Version="9.0.10" />
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
<PackageVersion Include="System.Numerics.Tensors" Version="9.0.11" />
<PackageVersion Include="System.Private.Uri" Version="4.3.2" />
<PackageVersion Include="System.Reactive" Version="6.0.1" />
<PackageVersion Include="System.Runtime.Caching" Version="9.0.10" />
@@ -118,6 +123,7 @@
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.10" />
<PackageVersion Include="System.Text.Json" Version="9.0.10" />
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
<PackageVersion Include="ToolGood.Words.Pinyin" Version="3.1.0.3" />
<PackageVersion Include="UnicodeInformation" Version="2.6.0" />
<PackageVersion Include="UnitsNet" Version="5.56.0" />
<PackageVersion Include="UTF.Unknown" Version="2.6.0" />

View File

@@ -75,6 +75,37 @@ OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
```
### ToolGood.Words.Pinyin
We use the ToolGood.Words.Pinyin NuGet package for converting Chinese characters to pinyin.
**Source**: [https://github.com/toolgood/ToolGood.Words.Pinyin](https://github.com/toolgood/ToolGood.Words.Pinyin)
```
MIT License
Copyright (c) 2020 ToolGood
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
## Utility: Command Palette Built-in Extensions
### Calculator
@@ -1532,6 +1563,7 @@ SOFTWARE.
- SkiaSharp.Views.WinUI
- StreamJsonRpc
- StyleCop.Analyzers
- ToolGood.Words.Pinyin
- UnicodeInformation
- UnitsNet
- UTF.Unknown

File diff suppressed because it is too large Load Diff

1045
PowerToys.slnx Normal file

File diff suppressed because it is too large Load Diff

34
doc/devdocs/commands.md Normal file
View File

@@ -0,0 +1,34 @@
# Issue/PR commands
The PowerToys repository uses some special keywords to help manage issues and pull requests. Here is a list of the most important commands you can use in issue and PR descriptions or comments.
| Command | Description |
|---------|-------------|
| `/azp run` | Triggers the Azure Pipelines CI build for the current PR. Useful if you want to re-run the build without creating a new commit. |
| `/bugreport` / `/reportbug` | Adds a comment with a manual for the Bug Report Tool, which helps users collect logs and system information for debugging purposes. It requests to upload this file and adds the `Needs-Author-Feedback` label. |
| `/feedbackhub` | Adds a comment with a link to the Feedback Hub app on Windows, where users can submit feedback about PowerToys. Closes the issue and adds the `Resolution-Please File on Feedback Hub` label. |
| `/dup #...` / `/duplicate #...` / `/dup https://...` / `/duplicate https://...` | Marks the current issue as a duplicate of another issue. It closes the current issue and applies the `Resolution-Duplicate` label. Replace `#...` with the issue number or a link to the issue. |
| `/needinfo` | Adds the `Needs-Author-Feedback` label to the issue or PR, indicating that more information is needed from the author. |
| `/helped` | Closes the issue and adds the `Resolution-Helped User` label. Furthermore a comment is added with a link to the PowerToys user documentation. |
| `/loc` | Adds a comment informing the user that the issue was forwarded to the localization team and will soon be fixed. It adds the `Loc-Sent To Team` label. |
## Defining new commands
Most of these commands are using the [Microsoft GitHub Policy Service](https://github.com/apps/microsoft-github-policy-service) bot. Its commands are defined in the [PowerToys policy configuration file](/.github/policies/resourceManagement.yml).
## Other automated tasks
### Automatic labeling
The bot can automatically apply the correct `product-...` label for any opened issue.
> [!NOTE]
> This feature is currently only available for the Workspaces module as a test.
### The `Needs-Author-Feedback` label
If an issue has this label and had no activity for 5 days, the bot will post a comment reminding the author to provide the needed information. It also adds the `Status-No recent activity` label. If no further activity occurs for another 5 days, the bot will close the issue.
### Filtering users that want to contribute
If a user utters their intention to contribute (e.g., by using the phrase "I want to contribute" in an issue or PR), the bot will add a comment with a link to the ["Would you like to contribute to PowerToys?" thread](https://github.com/microsoft/PowerToys/issues/28769).

View File

@@ -134,7 +134,7 @@ If you prefer, you can alternatively build prerequisite projects for the install
#### Locally compiling the installer
1. Open `installer\PowerToysSetup.sln`
1. Open `installer\PowerToysSetup.slnx`
1. In Visual Studio, in the `Solutions Configuration` drop-down menu select `Release`
1. From the `Build` menu choose `Build Solution`.
@@ -144,9 +144,9 @@ To build the installer from the command line, run `Developer Command Prompt for
```
git clean -xfd -e *exe -- .\installer\
MSBuild -t:restore .\installer\PowerToysSetup.sln -p:RestorePackagesConfig=true /p:Platform="x64" /p:Configuration=Release
MSBuild -t:Restore -m .\installer\PowerToysSetup.sln /t:PowerToysInstallerVNext /p:Configuration=Release /p:Platform="x64"
MSBuild -t:Restore -m .\installer\PowerToysSetup.sln /t:PowerToysBootstrapperVNext /p:Configuration=Release /p:Platform="x64"
MSBuild -t:restore .\installer\PowerToysSetup.slnx -p:RestorePackagesConfig=true /p:Platform="x64" /p:Configuration=Release
MSBuild -t:Restore -m .\installer\PowerToysSetup.slnx /t:PowerToysInstallerVNext /p:Configuration=Release /p:Platform="x64"
MSBuild -t:Restore -m .\installer\PowerToysSetup.slnx /t:PowerToysBootstrapperVNext /p:Configuration=Release /p:Platform="x64"
```
### Supported arguments for the .EXE Bootstrapper installer

View File

@@ -38,7 +38,7 @@ For C# modules, the settings are accessed through the `SettingsUtils` class in t
using Microsoft.PowerToys.Settings.UI.Library;
// Read settings
var settings = SettingsUtils.GetSettings<ModuleSettings>("ModuleName");
var settings = SettingsUtils.Default.GetSettings<ModuleSettings>("ModuleName");
bool enabled = settings.Enabled;
```
@@ -49,7 +49,7 @@ using Microsoft.PowerToys.Settings.UI.Library;
// Write settings
settings.Enabled = true;
SettingsUtils.SaveSettings(settings.ToJsonString(), "ModuleName");
SettingsUtils.Default.SaveSettings(settings.ToJsonString(), "ModuleName");
```
## Settings Handling in Modules

View File

@@ -19,7 +19,7 @@ You can build the entire solution from the command line, which is sometimes fast
2. Navigate to the repository root directory
3. Run the following command(don't forget to set the correct platform):
```pwsh
msbuild -restore -p:RestorePackagesConfig=true -p:Platform=ARM64 -m PowerToys.sln /tl /p:NuGetInteractive="true"
msbuild -restore -p:RestorePackagesConfig=true -p:Platform=ARM64 -m PowerToys.slnx /tl /p:NuGetInteractive="true"
```
4. This process should complete in approximately 13-14 minutes for a full build

View File

@@ -42,10 +42,10 @@ Or reach out to "tools\build\BUILD-GUIDELINES.md"
### Sample plain msbuild command
```powershell
# Restore:
msbuild powertoys.sln -t:restore -p:configuration=debug -p:platform=x64 -m
msbuild powertoys.slnx -t:restore -p:configuration=debug -p:platform=x64 -m
# Build powertoys sln
msbuild powertoys.sln -p:configuration=debug -p:platform=x64 -m
# Build powertoys slnx
msbuild powertoys.slnx -p:configuration=debug -p:platform=x64 -m
# dotnet project
msbuild src\settings-ui\Settings.UI\PowerToys.Settings.csproj -p:Platform=x64 -p:Configuration=Debug -m
@@ -122,7 +122,7 @@ Similar for attach to managed code.
| Task | Command / Action | Notes |
|------|------------------|-------|
| Clean | `git clean -xdf` (careful) or `msbuild /t:Clean PowerToys.sln` | Deep clean removes packages & build outputs |
| Clean | `git clean -xdf` (careful) or `msbuild /t:Clean PowerToys.slnx` | Deep clean removes packages & build outputs |
| Rebuild single project | `msbuild path\to\proj.vcxproj /t:Rebuild -p:Platform=x64 -p:Configuration=Debug` | Faster than whole solution |
| Generate installer (rare in inner loop) | See `tools\build\build-installer.ps1` | Usually not needed for local debug |
| Resource conversion errors | Re-run restore + build | Triggers custom PowerShell targets |
| Resource conversion errors | Re-run restore + build | Triggers custom PowerShell targets |

View File

@@ -12,7 +12,7 @@
- Exit PowerToys if it's running.
- Open `PowerToys.sln` in Visual Studio and build the solution.
- Open `PowerToys.slnx` in Visual Studio and build the solution.
- Run tests in the Test Explorer (`Test > Test Explorer` or `Ctrl+E, T`).

View File

@@ -1,165 +0,0 @@
# Localization
> **NOTE**: THIS DOCUMENT IS OUTDATED.
> Follow [issue 15243](https://github.com/microsoft/PowerToys/issues/15243) for updates.
## Table of Contents
1. [Localization on the pipeline (CDPX)](#localization-on-the-pipeline-cdpx)
1. [UWP Special case](#uwp-special-case)
2. [Enabling localization on a new project](#enabling-localization-on-a-new-project)
1. [C++](#c)
2. [C#](#c-1)
3. [UWP](#uwp)
3. [Lcl Files](#lcl-files)
4. [Possible Issues in localization PRs (LEGO)](#possible-issues-in-localization-prs-lego)
5. [Enabling localized MSI for a new project](#enabling-localized-msi-for-a-new-project)
## Localization on the pipeline (CDPX)
[The localization step](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/pipeline.user.windows.yml#L45-L52) is run on the pipeline before the solution is built. This step runs the [build-localization](https://github.com/microsoft/PowerToys/blob/main/.pipelines/build-localization.cmd) script, which generates resx files for all the projects with localization enabled using the `Localization.XLoc` package.
The [`Localization.XLoc`](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/build-localization.cmd#L24-L25) tool is run on the repo root, and it checks for all occurrences of `LocProject.json`. Each localized project has a `LocProject.json` file in the project root, which contains the location of the English resx file, list of languages for localization, and the output path where the localized resx files are to be copied to. In addition to this, some other parameters can be set, such as whether the language ID should be added as a folder in the file path or in the file name. When the CDPX pipeline is run, the localization team is notified of changes in the English resx files. For each project with localization enabled, a `loc` folder (see [this](https://github.com/microsoft/PowerToys/tree/main/src/modules/launcher/Microsoft.Launcher/loc) for example) is created in the same directory as the `LocProject.json` file. The folder contains language specific folders which in turn have a nested folder path equivalent to `OutputPath` in the `LocProject.json`. Each of these folders contain one `lcl` file. The `lcl` files contain the English resources along with their translation for that language. These are described in more detail in the [Lcl files section](#lcl-files). Once the `.resx` files are generated, they will be used during the `Build PowerToys` step for localized versions of the modules.
Since the localization script requires certain nuget packages, the [`restore-localization`](https://github.com/microsoft/PowerToys/blob/main/.pipelines/restore-localization.cmd) script is run before running `build-localization` to install all the required packages. This script must [run in the `restore` step](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/pipeline.user.windows.yml#L37-L39) of pipeline because [the host is network isolated](https://onebranch.visualstudio.com/Pipeline/_wiki/wikis/Pipeline.wiki/2066/Consuming-Packages-in-a-CDPx-Pipeline?anchor=overview) at the `build` step. The [Toolset package source](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/pipeline.user.windows.yml#L23) is used for this.
The process and variables that can be tweaked on the pipeline are described in more detail on [onebranch (account required) under Localization](https://onebranch.visualstudio.com/Pipeline/_wiki/wikis/Pipeline.wiki/290/Localization).
The localized resource dlls for C# projects are added to the MSI only for build on the pipeline. This is done by checking if the [`IsPipeline` variable is defined](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/installer/PowerToysSetup/Product.wxs#L804-L805), which gets defined before [building the installer on the pipeline](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/.pipelines/build-installer.cmd#L4). This is done because the localized resx files are only present on the pipeline, and not having this check would result in the installer project failing to build locally.
## Enabling localization on a new project
To enable localization on a new project, the first step is to create a file `LocProject.json` in the project root.
For example, for a project in the folder `src\path` where the resx file is present in `resources\Resources.resx`, the LocProject.json file will contain the following:
```
{
"Projects": [
{
"LanguageSet": "Azure_Languages",
"LocItems": [
{
"SourceFile": "src\\path\\resources\\Resources.resx",
"CopyOption": "LangIDOnName",
"OutputPath": "src\\path\\resources"
}
]
}
]
}
```
The rest of the steps depend on the project type and are covered in the sections below. The steps to add the localized files to the MSI can be found in [Enabling localized MSI for a new project](#Enabling-localized-MSI-for-a-new-project).
### C++
C++ projects do not support `resx` files, and instead use `rc` files along with `resource.h` files. The CDPX pipeline however doesn't support localizing `rc` files and the other alternative they support is directly translating the resources from the binary which makes it harder to maintain resources. To avoid this, a custom script has been added which expects a resx file and converts the entries to an rc file with a string table and adds resource declarations to a resource.h file so that the resources can be compiled with the C++ project.
If you already have a .rc file, copy the string table to a separate txt file and run the [convert-stringtable-to-resx.ps1](https://github.com/microsoft/PowerToys/blob/main/tools/build/convert-stringtable-to-resx.ps1) script on it. This script is not very robust to input, and requires the data in a specific format, where `IDS_ResName L"ResourceValue"` and any number of spaces can be present in between. The script converts this file to the format expected by [`resgen`](https://learn.microsoft.com/dotnet/framework/tools/resgen-exe-resource-file-generator#Convert), which will convert it to resx. The resource names are changed from all uppercase to title case, and the `IDS_` prefix is removed. Escape characters might have to be manually replaced, for example .rc files would have escaped double quotes as `""`, so this should be replaced with just `"` before converting to the resx files.
After generating the resx file, rename the existing rc and h files to ProjName.base.rc and resource.base.h. In the rc file remove the string table which is to be localized and in the .h file remove all `#define`s corresponding to localized resources. In the vcxproj of the C++ project, add the following build event:
```
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(SolutionDir)tools\build\convert-resx-to-rc.ps1 $(MSBuildThisFileDirectory) resource.base.h resource.h ProjName.base.rc ProjName.rc" />
</Target>
```
This event runs a script which generates a resource.h and ProjName.rc in the `Generated Files` folder using the strings in all the resx files along with the existing information in resource.base.h and ProjName.base.rc. The script is [convert-resx-to-rc.ps1](https://github.com/microsoft/PowerToys/blob/main/tools/build/convert-resx-to-rc.ps1). The script uses [`resgen`](https://learn.microsoft.com/dotnet/framework/tools/resgen-exe-resource-file-generator#Convert) to convert the resx file to a string table expected in the .rc file format. When the resources are added to the rc file the `IDS_` prefix is added and resource names are in upper case (as it was originally). Any occurrences of `"` in the string resource is escaped as `""` to prevent build errors. The string tables are added to the rc file in the following format:
```
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
STRINGTABLE
BEGIN
strings
END
#endif
```
Since there is no API to identify the `AFX_TARG_*`, `LANG_*` or `SUBLANG_*` values from each langId from the pipeline, these are hardcoded in the script (for each language) as done in [lines 50-77 of `convert-resx-to-rc.ps1`](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/tools/build/convert-resx-to-rc.ps1#L50-L77). **If any other languages are added in the future, this script will have to be updated.** In order to determine what are the language codes, you can open the rc file in Resource View, right click the string table and press `Insert Copy` and choose the corresponding language. This autogenerates the required code and can be used to figure out the language codes. The files also add the resource declarations to a resource.h file, starting from 101 by default(this can be changed by an optional argument). Since the output files will be generated in `Generated Files`, any includes in these two files will require an additional `..\` and wherever resource.h is used, it will have to be included as `Generated Files\resource.h`. While adding `resource.base.h` and `ProjName.base.rc` to the vcxproj, these should be modified to not participate in the build to avoid build errors:
```
<None Include="Resources.resx" />
```
Some rc/resource.h files might be used in multiple projects (for example, KBM). To ensure the projects build for these cases, the build event can be added to the entire directory so that the rc files are generated before any project is built. See [Directory.Build.targets](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/Directory.Build.targets) for an example.
Check [this PR](https://github.com/microsoft/PowerToys/pull/6104) for an example for making these changes for a C++ project.
### C#
Since C# projects natively support `resx` files, the only step required here is to include all the resx files in the build. For .NET Core projects this is done automatically and the .csproj does not need to be modified. For other projects, the following line needs to be added:
```
<EmbeddedResource Include="Properties\Resources.*.resx" />
```
**Note:** Building with localized resources may cause a build warning `Referenced assembly 'mscorlib.dll' targets a different processor` which is a VS bug. More details can be found in [PowerToys issue #7269](https://github.com/microsoft/PowerToys/issues/7269).
**Note:** If a project needs to be migrated from XAML resources to resx, the easiest way to convert the resources would be to change to format to `=` separates resources by either manually (by Ctrl+H on a text editor), or by a script, and then running [`resgen`](https://learn.microsoft.com/dotnet/framework/tools/resgen-exe-resource-file-generator#Convert) on `Developer Command Prompt for VS` to convert it to resx format.
```
<system:String x:Key="wox_plugin_calculator_plugin_name">Calculator</system:String>
<system:String x:Key="wox_plugin_calculator_plugin_description">Allows to do mathematical calculations.(Try 5*3-2 in Wox)</system:String>
<system:String x:Key="wox_plugin_calculator_not_a_number">Not a number (NaN)</system:String>
```
to
```
wox_plugin_calculator_plugin_name=Calculator
wox_plugin_calculator_plugin_description=Allows to do mathematical calculations.(Try 5*3-2 in Wox)
wox_plugin_calculator_not_a_number=Not a number (NaN)
```
After adding the resx file to the project along with the resource generator, references to the strings will have to be replaced with `Properties.Resources.resName` rather than the custom APIs. Check [this PR](https://github.com/microsoft/PowerToys/pull/6165) for an example of the changes required.
### UWP
UWP projects expect `resw` files rather than `resx` (the format is almost the same). Unlike other C# projects, the files are expected in the format `fullLangId\Resources.resw`. To include these files in the build, replace the following line in the csproj:
```
<PRIResource Include="Strings\en-us\Resources.resw" />
```
to
```
<PRIResource Include="Strings\*\Resources.resw" />
```
## Lcl Files
Lcl files contain all the resources that are present in the English resx file, along with a translation if it has been added.
For example, an entry for a resource in the lcl file looks like this:
```
<Item ItemId=";EditKeyboard_WindowName" ItemType="0;.resx" PsrId="211" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Remap keys]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Remapper des touches]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
```
The `<Tgt>` element would not be present in the initial commits of the lcl files, as only the English version of the string would be present.
**Note:** The CDPX Localization system has a fail-safe check on the lcl files, where if the English string value which is present inside `<Val><![CDATA[*]]></Val>` does not match the value present in the English Resources.resx file then the translated value will not be copied to the localized resx file. This is present so that obsolete translations would not be loaded when the English resource has changed, and the English string will be used rather than the obsolete translation.
## Possible Issues in localization PRs (LEGO)
Since the LEGO PRs update some of the strings in LCL files at a time, there can be multiple PRs which modify the same files, leading to merge conflicts. In most cases this would show up on GitHub as a merge conflict, but sometimes a bad git merge may occur, and the file could end up with incorrect formatting, such as two `<Tgt>` elements for a single resource. These can be fixed by ensuring the elements follow the format described in [this section](#lcl-files). To catch such errors, the build farm should be run for every LEGO PR and if any error occurs in the localization step, we should check the corresponding resx/lcl files for conflicts.
## Enabling localized MSI for a new project
For C++ and UWP projects no additional files are generated with localization that need to be added to the MSI. For C++ projects all the resources are added to the dll/exe, while for UWP projects they are added to the `resources.pri` file (which is present even for an unlocalized project). To verify if the localized resources are added to the `resources.pri` file the following steps can be done:
- Open `Developer Command Prompt for VS`
- After navigating to the folder containing the pri file, run the following command:
makepri.exe dump /if .\resources.pri
- Check the contents of the `resources.pri.xml` file that is generated from the command. The last section of the file will contain the resources with the strings in all the languages:
```
<NamedResource name="GeneralSettings_RunningAsAdminText" uri="ms-resource://f4f787a5-f0ae-47a9-be89-5408b1dd2b47/Resources/GeneralSettings_RunningAsAdminText">
<Candidate qualifiers="Language-FR" type="String">
<Value>Running as administrator</Value>
</Candidate>
<Candidate qualifiers="Language-EN-US" isDefault="true" type="String">
<Value>Running as administrator</Value>
</Candidate>
</NamedResource>
```
For C# projects, satellite dlls are generated when the project is built. For a project named `ProjName`, files are created in the format `langId\ProjName.resources.dll` where `langId` is in the same format as the lcl files. The satellite dlls need to be included with the MSI, but they must be added only if the solution is built from the build farm, as the localized resx files will not be present on local machines (and that could cause local builds of the installer to fail).
This can be done by adding the directory name of the project to [Product.wxs near line 806](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/installer/PowerToysSetup/Product.wxs#L806) and a resource component for the project can be created in [Product.wxs near lines 845-847](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/installer/PowerToysSetup/Product.wxs#L845-L847) in this format:
```
<Component Id="ProjName_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)ProjNameInstallFolder">
<File Id="ProjName_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\ProjName\$(var.Language)\ProjName.resources.dll" />
</Component>
```
We should also ensure the new dlls are signed by the pipeline. Currently all dlls of the form [`*.resources.dll` are signed](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/.pipelines/pipeline.user.windows.yml#L68).
**Note:** The resource dlls should be added to the MSI project only after the initial commit with the lcl files has been done by the Localization team. Otherwise, the pipeline will fail as there wouldn't be any resx files to generate the dlls.

View File

@@ -86,7 +86,7 @@ The module provides a user interface for configuring settings in the PowerToys S
### Building and Testing
1. Clone the repository: `git clone https://github.com/microsoft/PowerToys.git`
2. Open PowerToys.sln in Visual Studio
2. Open PowerToys.slnx in Visual Studio
3. Select the Release configuration and build the solution
4. Run PowerToys.exe from the output directory to test the module

View File

@@ -161,7 +161,7 @@ FancyZones is divided into several projects:
```
git clone https://github.com/microsoft/PowerToys.git
```
2. Open `PowerToys.sln` in Visual Studio
2. Open `PowerToys.slnx` in Visual Studio
3. Select the Release configuration and build the solution
4. If you encounter build errors, try deleting the x64 output folder and rebuild
@@ -244,7 +244,7 @@ UI tests are implemented using [Windows Application Driver](https://github.com/m
- Exit PowerToys if it's running
- Run WinAppDriver.exe from the installation directory. Skip this step if installed in the default directory (`C:\Program Files (x86)\Windows Application Driver`); in this case, it'll be launched automatically during tests.
- Open `PowerToys.sln` in Visual Studio and build the solution.
- Open `PowerToys.slnx` in Visual Studio and build the solution.
- Run tests in the Test Explorer (`Test > Test Explorer` or `Ctrl+E, T`).
>Note: notifications or other application windows, that are shown above the window under test, can disrupt the testing process.

View File

@@ -11,7 +11,7 @@ Keyboard Manager consists of two main components:
## Development Environment Setup
1. Clone the PowerToys repository
2. Open `PowerToys.sln` in Visual Studio
2. Open `PowerToys.slnx` in Visual Studio
3. Ensure all NuGet packages are restored
4. Build the entire solution in Debug configuration
@@ -91,4 +91,4 @@ If you encounter issues with multiple instances, check the mutex logic in `Keybo
To debug both the Editor and Engine:
1. Launch the Engine first in debug mode
2. Attach the debugger to the Editor process when it starts
2. Attach the debugger to the Editor process when it starts

View File

@@ -92,7 +92,7 @@ The modules settings are exposed in the PowerToys Settings UI. Options includ
3. Build the solution:
```sh
msbuild -restore -p:RestorePackagesConfig=true -p:Platform=ARM64 -m PowerToys.sln
msbuild -restore -p:RestorePackagesConfig=true -p:Platform=ARM64 -m PowerToys.slnx
```
> Note: This may take some time.

View File

@@ -53,7 +53,7 @@ The Screen Ruler module consists of several components:
### Building
1. Open PowerToys.sln in Visual Studio
1. Open PowerToys.slnx in Visual Studio
2. In the Solutions Configuration drop-down menu, select Release or Debug
3. From the Build menu, choose Build Solution
4. The executable app for Screen Ruler is named PowerToys.MeasureToolUI.exe

View File

@@ -19,7 +19,7 @@ Shortcut Guide is a PowerToy that displays an overlay of available keyboard shor
## Build and Debug Instructions
### Build
1. Open PowerToys.sln in Visual Studio
1. Open PowerToys.slnx in Visual Studio
2. Select Release or Debug in the Solutions Configuration drop-down menu
3. From the Build menu, choose Build Solution
4. The executable is named PowerToys.ShortcutGuide.exe

View File

@@ -38,6 +38,11 @@ Welcome to the PowerToys developer documentation. This documentation provides in
- [Update Process](processes/update-process.md) - How PowerToys updates work
- [GPO Implementation](processes/gpo.md) - Group Policy Objects implementation details
## Other Resources
- [aka.ms links](akaLinks.md) - List of short links
- [Issue/PR commands](commands.md) - Special commands for managing issues and pull requests
## Fork, Clone, Branch and Create your PR
Once you've discussed your proposed feature/fix/etc. with a team member, and an approach or a spec has been written and approved, it's time to start development:
@@ -80,7 +85,7 @@ Once you've discussed your proposed feature/fix/etc. with a team member, and an
### Install Visual Studio dependencies
1. Open the `PowerToys.sln` file.
1. Open the `PowerToys.slnx` file.
1. If you see a dialog that says `install extra components` in the solution explorer pane, click `install`
### Get Submodules to compile
@@ -93,7 +98,7 @@ We have submodules that need to be initialized before you can compile most parts
### Compiling Source Code
- Open `PowerToys.sln` in Visual Studio.
- Open `PowerToys.slnx` in Visual Studio.
- In the `Solutions Configuration` drop-down menu select `Release` or `Debug`.
- From the `Build` menu choose `Build Solution`, or press <kbd>Control</kbd>+<kbd>Shift</kbd>+<kbd>b</kbd> on your keyboard.
- The build process may take several minutes depending on your computer's performance. Once it completes, the PowerToys binaries will be in your repo under `x64\Release\`.
@@ -107,10 +112,10 @@ Our installer is two parts, an EXE and an MSI. The EXE (Bootstrapper) contains
The installer can only be compiled in `Release` mode; steps 1 and 2 must be performed before the MSI can be compiled.
1. Compile `PowerToys.sln`. Instructions are listed above.
1. Compile `PowerToys.slnx`. Instructions are listed above.
1. Compile `BugReportTool.sln` tool. Path from root: `tools\BugReportTool\BugReportTool.sln` (details listed below)
1. Compile `StylesReportTool.sln` tool. Path from root: `tools\StylesReportTool\StylesReportTool.sln` (details listed below)
1. Compile `PowerToysSetup.sln` Path from root: `installer\PowerToysSetup.sln` (details listed below)
1. Compile `PowerToysSetup.slnx` Path from root: `installer\PowerToysSetup.slnx` (details listed below)
See [Installer](core/installer.md) for more details on building and debugging the installer.

View File

@@ -51,6 +51,7 @@ Contact the developers of a plugin directly for assistance with a specific plugi
| [RandomGen](https://github.com/ruslanlap/PowerToysRun-RandomGen) | [ruslanlap](https://github.com/ruslanlap) | 🎲 Generate random data instantly with a single keystroke. Perfect for developers, testers, designers, and anyone who needs quick access to random data. Features include secure passwords, PINs, names, business data, dates, numbers, GUIDs, color codes, and more. Especially useful for designers who need random color codes and placeholder content. |
| [Open With Cursor](https://github.com/VictorNoxx/PowerToys-Run-Cursor/) | [VictorNoxx](https://github.com/VictorNoxx) | Open Visual Studio, VS Code recents with Cursor AI |
| [CheatSheets](https://github.com/ruslanlap/PowerToysRun-CheatSheets) | [ruslanlap](https://github.com/ruslanlap) | 📚 Find cheat sheets and command examples instantly from tldr pages, cheat.sh, and devhints.io. Features include favorites system, categories, offline mode, and smart caching. |
| [QuickAI](https://github.com/ruslanlap/PowerToysRun-QuickAi) | [ruslanlap](https://github.com/ruslanlap) | AI-powered assistance with instant, smart responses from multiple providers (Groq, Together, Fireworks, OpenRouter, Cohere) |
## Extending software plugins

View File

@@ -1,96 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.1.32414.318
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spdlog", "..\src\logging\logging.vcxproj", "{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "logger", "..\src\common\logger\logger.vcxproj", "{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Version", "..\src\common\version\version.vcxproj", "{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EtwTrace", "..\src\common\Telemetry\EtwTrace\EtwTrace.vcxproj", "{8F021B46-362B-485C-BFBA-CCF83E820CBD}"
EndProject
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "PowerToysInstallerVNext", "PowerToysSetupVNext\PowerToysInstallerVNext.wixproj", "{B6E94700-DF38-41F6-A3FD-18B69674AB1E}"
EndProject
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "PowerToysBootstrapperVNext", "PowerToysSetupVNext\PowerToysBootstrapperVNext.wixproj", "{DA4E9744-80BE-424C-B0F5-AFD8757DB575}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerToysSetupCustomActionsVNext", "PowerToysSetupCustomActionsVNext\PowerToysSetupCustomActionsVNext.vcxproj", "{B3A354B0-1E54-4B55-A962-FB5AF9330C19}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SilentFilesInUseBAFunction", "PowerToysSetupVNext\SilentFilesInUseBA\SilentFilesInUseBAFunction.vcxproj", "{F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64
Release|ARM64 = Release|ARM64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|ARM64.ActiveCfg = Debug|ARM64
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|x64.ActiveCfg = Debug|x64
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|x64.Build.0 = Debug|x64
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|ARM64.ActiveCfg = Release|ARM64
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|ARM64.Build.0 = Release|ARM64
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|x64.ActiveCfg = Release|x64
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|x64.Build.0 = Release|x64
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Debug|ARM64.ActiveCfg = Debug|ARM64
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Debug|x64.ActiveCfg = Debug|x64
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Debug|x64.Build.0 = Debug|x64
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|ARM64.ActiveCfg = Release|ARM64
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|ARM64.Build.0 = Release|ARM64
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|x64.ActiveCfg = Release|x64
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|x64.Build.0 = Release|x64
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|ARM64.ActiveCfg = Debug|ARM64
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|ARM64.Build.0 = Debug|ARM64
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|x64.ActiveCfg = Debug|x64
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|x64.Build.0 = Debug|x64
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|ARM64.ActiveCfg = Release|ARM64
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|ARM64.Build.0 = Release|ARM64
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|x64.ActiveCfg = Release|x64
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|x64.Build.0 = Release|x64
{8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|ARM64.ActiveCfg = Debug|ARM64
{8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|ARM64.Build.0 = Debug|ARM64
{8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|x64.ActiveCfg = Debug|x64
{8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|x64.Build.0 = Debug|x64
{8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|ARM64.ActiveCfg = Release|ARM64
{8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|ARM64.Build.0 = Release|ARM64
{8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|x64.ActiveCfg = Release|x64
{8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|x64.Build.0 = Release|x64
{B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Debug|ARM64.ActiveCfg = Debug|ARM64
{B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Debug|ARM64.Build.0 = Debug|ARM64
{B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Debug|x64.ActiveCfg = Debug|x64
{B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Debug|x64.Build.0 = Debug|x64
{B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Release|ARM64.ActiveCfg = Release|ARM64
{B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Release|ARM64.Build.0 = Release|ARM64
{B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Release|x64.ActiveCfg = Release|x64
{B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Release|x64.Build.0 = Release|x64
{DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Debug|ARM64.ActiveCfg = Debug|ARM64
{DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Debug|ARM64.Build.0 = Debug|ARM64
{DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Debug|x64.ActiveCfg = Debug|x64
{DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Debug|x64.Build.0 = Debug|x64
{DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Release|ARM64.ActiveCfg = Release|ARM64
{DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Release|ARM64.Build.0 = Release|ARM64
{DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Release|x64.ActiveCfg = Release|x64
{DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Release|x64.Build.0 = Release|x64
{B3A354B0-1E54-4B55-A962-FB5AF9330C19}.Debug|ARM64.ActiveCfg = Debug|ARM64
{B3A354B0-1E54-4B55-A962-FB5AF9330C19}.Debug|x64.ActiveCfg = Debug|x64
{B3A354B0-1E54-4B55-A962-FB5AF9330C19}.Debug|x64.Build.0 = Debug|x64
{B3A354B0-1E54-4B55-A962-FB5AF9330C19}.Release|ARM64.ActiveCfg = Release|ARM64
{B3A354B0-1E54-4B55-A962-FB5AF9330C19}.Release|ARM64.Build.0 = Release|ARM64
{B3A354B0-1E54-4B55-A962-FB5AF9330C19}.Release|x64.ActiveCfg = Release|x64
{B3A354B0-1E54-4B55-A962-FB5AF9330C19}.Release|x64.Build.0 = Release|x64
{F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}.Debug|ARM64.ActiveCfg = Debug|ARM64
{F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}.Debug|x64.ActiveCfg = Debug|x64
{F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}.Debug|x64.Build.0 = Debug|x64
{F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}.Release|ARM64.ActiveCfg = Release|ARM64
{F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}.Release|ARM64.Build.0 = Release|ARM64
{F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}.Release|x64.ActiveCfg = Release|x64
{F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B7A3DA30-D443-40FF-AC51-988AD41E3962}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,22 @@
<Solution>
<Configurations>
<Platform Name="ARM64" />
<Platform Name="x64" />
</Configurations>
<Project Path="../src/common/logger/logger.vcxproj" Id="d9b8fc84-322a-4f9f-bbb9-20915c47ddfd">
<Build Solution="Debug|ARM64" Project="false" />
</Project>
<Project Path="../src/common/Telemetry/EtwTrace/EtwTrace.vcxproj" Id="8f021b46-362b-485c-bfba-ccf83e820cbd" />
<Project Path="../src/common/version/version.vcxproj" Id="cc6e41ac-8174-4e8a-8d22-85dd7f4851df" />
<Project Path="../src/logging/logging.vcxproj" Id="7e1e3f13-2bd6-3f75-a6a7-873a2b55c60f">
<Build Solution="Debug|ARM64" Project="false" />
</Project>
<Project Path="PowerToysSetupCustomActionsVNext/PowerToysSetupCustomActionsVNext.vcxproj" Id="b3a354b0-1e54-4b55-a962-fb5af9330c19">
<Build Solution="Debug|ARM64" Project="false" />
</Project>
<Project Path="PowerToysSetupVNext/PowerToysBootstrapperVNext.wixproj" Type="b7dd6f7e-def8-4e67-b5b7-07ef123db6f0" />
<Project Path="PowerToysSetupVNext/PowerToysInstallerVNext.wixproj" Type="b7dd6f7e-def8-4e67-b5b7-07ef123db6f0" />
<Project Path="PowerToysSetupVNext/SilentFilesInUseBA/SilentFilesInUseBAFunction.vcxproj" Id="f8b9f842-f5c3-4a2d-8c85-7f8b9e2b4f1d">
<Build Solution="Debug|ARM64" Project="false" />
</Project>
</Solution>

View File

@@ -21,7 +21,7 @@ namespace Microsoft.PowerToys.UITest
public class SettingsConfigHelper
{
private static readonly JsonSerializerOptions IndentedJsonOptions = new() { WriteIndented = true };
private static readonly SettingsUtils SettingsUtils = new SettingsUtils();
private static readonly SettingsUtils SettingsUtils = SettingsUtils.Default;
/// <summary>
/// Configures global PowerToys settings to enable only specified modules and disable all others.

View File

@@ -16,9 +16,54 @@
namespace registry
{
namespace detail
{
struct on_exit
{
std::function<void()> f;
on_exit(std::function<void()> f) :
f{ std::move(f) } {}
~on_exit() { f(); }
};
template<class... Ts>
struct overloaded : Ts...
{
using Ts::operator()...;
};
template<class... Ts>
overloaded(Ts...) -> overloaded<Ts...>;
inline const wchar_t* getScopeName(HKEY scope)
{
if (scope == HKEY_LOCAL_MACHINE)
{
return L"HKLM";
}
else if (scope == HKEY_CURRENT_USER)
{
return L"HKCU";
}
else if (scope == HKEY_CLASSES_ROOT)
{
return L"HKCR";
}
else
{
return L"HK??";
}
}
}
namespace install_scope
{
const wchar_t INSTALL_SCOPE_REG_KEY[] = L"Software\\Classes\\powertoys\\";
const wchar_t UNINSTALL_REG_KEY[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
// Bundle UpgradeCode from PowerToys.wxs (with braces as stored in registry)
const wchar_t BUNDLE_UPGRADE_CODE[] = L"{6341382D-C0A9-4238-9188-BE9607E3FAB2}";
enum class InstallScope
{
@@ -26,8 +71,67 @@ namespace registry
PerUser,
};
// Helper function to find PowerToys bundle in Windows Uninstall registry by BundleUpgradeCode
inline bool find_powertoys_bundle_in_uninstall_registry(HKEY rootKey)
{
HKEY uninstallKey{};
if (RegOpenKeyExW(rootKey, UNINSTALL_REG_KEY, 0, KEY_READ, &uninstallKey) != ERROR_SUCCESS)
{
return false;
}
detail::on_exit closeUninstallKey{ [uninstallKey] { RegCloseKey(uninstallKey); } };
DWORD index = 0;
wchar_t subKeyName[256];
// Enumerate all subkeys under Uninstall
while (RegEnumKeyW(uninstallKey, index++, subKeyName, 256) == ERROR_SUCCESS)
{
HKEY productKey{};
if (RegOpenKeyExW(uninstallKey, subKeyName, 0, KEY_READ, &productKey) != ERROR_SUCCESS)
{
continue;
}
detail::on_exit closeProductKey{ [productKey] { RegCloseKey(productKey); } };
// Check BundleUpgradeCode value (specific to WiX Bundle installations)
wchar_t bundleUpgradeCode[256]{};
DWORD bundleUpgradeCodeSize = sizeof(bundleUpgradeCode);
if (RegQueryValueExW(productKey, L"BundleUpgradeCode", nullptr, nullptr,
reinterpret_cast<LPBYTE>(bundleUpgradeCode), &bundleUpgradeCodeSize) == ERROR_SUCCESS)
{
if (_wcsicmp(bundleUpgradeCode, BUNDLE_UPGRADE_CODE) == 0)
{
return true;
}
}
}
return false;
}
inline const InstallScope get_current_install_scope()
{
// 1. Check HKCU Uninstall registry first (user-level bundle)
// Note: MSI components are always in HKLM regardless of install scope,
// but the Bundle entry will be in HKCU for per-user installations
if (find_powertoys_bundle_in_uninstall_registry(HKEY_CURRENT_USER))
{
Logger::info(L"Found user-level PowerToys bundle via BundleUpgradeCode in HKCU");
return InstallScope::PerUser;
}
// 2. Check HKLM Uninstall registry (machine-level bundle)
if (find_powertoys_bundle_in_uninstall_registry(HKEY_LOCAL_MACHINE))
{
Logger::info(L"Found machine-level PowerToys bundle via BundleUpgradeCode in HKLM");
return InstallScope::PerMachine;
}
// 3. Fallback to legacy custom registry key detection
Logger::info(L"PowerToys bundle not found in Uninstall registry, falling back to legacy detection");
// Open HKLM key
HKEY perMachineKey{};
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
@@ -45,6 +149,7 @@ namespace registry
&perUserKey) != ERROR_SUCCESS)
{
// both keys are missing
Logger::warn(L"No PowerToys installation detected, defaulting to PerMachine");
return InstallScope::PerMachine;
}
else
@@ -96,47 +201,6 @@ namespace registry
template<class>
inline constexpr bool always_false_v = false;
namespace detail
{
struct on_exit
{
std::function<void()> f;
on_exit(std::function<void()> f) :
f{ std::move(f) } {}
~on_exit() { f(); }
};
template<class... Ts>
struct overloaded : Ts...
{
using Ts::operator()...;
};
template<class... Ts>
overloaded(Ts...) -> overloaded<Ts...>;
inline const wchar_t* getScopeName(HKEY scope)
{
if (scope == HKEY_LOCAL_MACHINE)
{
return L"HKLM";
}
else if (scope == HKEY_CURRENT_USER)
{
return L"HKCU";
}
else if (scope == HKEY_CLASSES_ROOT)
{
return L"HKCR";
}
else
{
return L"HK??";
}
}
}
struct ValueChange
{
using value_t = std::variant<DWORD, std::wstring>;

View File

@@ -18,7 +18,7 @@ namespace PowerToys.DSC.UnitTests.SettingsResourceTests;
public abstract class SettingsResourceModuleTest<TSettingsConfig> : BaseDscTest
where TSettingsConfig : ISettingsConfig, new()
{
private readonly SettingsUtils _settingsUtils = new();
private readonly SettingsUtils _settingsUtils = SettingsUtils.Default;
private TSettingsConfig _originalSettings;
protected TSettingsConfig DefaultSettings => new();

View File

@@ -18,7 +18,7 @@ namespace PowerToys.DSC.Models.FunctionData;
public sealed class SettingsFunctionData<TSettingsConfig> : BaseFunctionData, ISettingsFunctionData
where TSettingsConfig : ISettingsConfig, new()
{
private static readonly SettingsUtils _settingsUtils = new();
private static readonly SettingsUtils _settingsUtils = SettingsUtils.Default;
private static readonly TSettingsConfig _settingsConfig = new();
private readonly SettingsResourceObject<TSettingsConfig> _input;

View File

@@ -0,0 +1,56 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using AdvancedPaste.Converters;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Windows.UI;
namespace AdvancedPaste.UnitTests.ConvertersTests;
[TestClass]
public sealed class HexColorToColorConverterTests
{
[TestMethod]
public void TestConvert_ValidSixDigitHex_ReturnsColor()
{
Color? result = HexColorConverterHelper.ConvertHexColorToRgb("#FFBFAB");
Assert.IsNotNull(result);
var color = (Windows.UI.Color)result;
Assert.AreEqual(255, color.R);
Assert.AreEqual(191, color.G);
Assert.AreEqual(171, color.B);
Assert.AreEqual(255, color.A);
}
[TestMethod]
public void TestConvert_ValidThreeDigitHex_ReturnsColor()
{
Color? result = HexColorConverterHelper.ConvertHexColorToRgb("#abc");
Assert.IsNotNull(result);
var color = (Windows.UI.Color)result;
// #abc should expand to #aabbcc
Assert.AreEqual(170, color.R); // 0xaa
Assert.AreEqual(187, color.G); // 0xbb
Assert.AreEqual(204, color.B); // 0xcc
Assert.AreEqual(255, color.A);
}
[TestMethod]
public void TestConvert_NullOrEmpty_ReturnsNull()
{
Assert.IsNull(HexColorConverterHelper.ConvertHexColorToRgb(null));
Assert.IsNull(HexColorConverterHelper.ConvertHexColorToRgb(string.Empty));
Assert.IsNull(HexColorConverterHelper.ConvertHexColorToRgb(" "));
}
[TestMethod]
public void TestConvert_InvalidHex_ReturnsNull()
{
Assert.IsNull(HexColorConverterHelper.ConvertHexColorToRgb("#GGGGGG"));
Assert.IsNull(HexColorConverterHelper.ConvertHexColorToRgb("#12345"));
}
}

View File

@@ -0,0 +1,36 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using AdvancedPaste.Helpers;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace AdvancedPaste.UnitTests.HelpersTests;
[TestClass]
public sealed class ClipboardItemHelperTests
{
[TestMethod]
[DataRow("#FFBFAB", true)]
[DataRow("#000000", true)]
[DataRow("#FFFFFF", true)]
[DataRow("#fff", true)]
[DataRow("#abc", true)]
[DataRow("#123456", true)]
[DataRow("#AbCdEf", true)]
[DataRow("FFBFAB", false)] // Missing #
[DataRow("#GGGGGG", false)] // Invalid hex characters
[DataRow("#12345", false)] // Wrong length
[DataRow("#1234567", false)] // Too long
[DataRow("", false)]
[DataRow(null, false)]
[DataRow(" #FFF ", true)] // Whitespace should be trimmed
[DataRow("Not a color", false)]
[DataRow("#", false)]
[DataRow("##FFFFFF", false)]
public void TestIsRgbHexColor(string input, bool expected)
{
bool result = ClipboardItemHelper.IsRgbHexColor(input);
Assert.AreEqual(expected, result, $"IsRgbHexColor(\"{input}\") should return {expected}");
}
}

View File

@@ -11,6 +11,7 @@
mc:Ignorable="d">
<UserControl.Resources>
<converters:DateTimeToFriendlyStringConverter x:Key="DateTimeToFriendlyStringConverter" />
<converters:HexColorToBrushConverter x:Key="HexColorToBrushConverter" />
<tkconverters:BoolToVisibilityConverter x:Name="BoolToVisibilityConverter" />
</UserControl.Resources>
<Grid ColumnSpacing="12">
@@ -25,6 +26,26 @@
Source="{x:Bind ClipboardItem.Image, Mode=OneWay}"
Stretch="UniformToFill"
Visibility="{x:Bind HasImage, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
<!-- Color preview with text -->
<Grid Visibility="{x:Bind HasColor, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Ellipse
Grid.Column="0"
Width="8"
Height="8"
Margin="8,0,8,0"
Fill="{x:Bind ClipboardItem.Content, Mode=OneWay, Converter={StaticResource HexColorToBrushConverter}}" />
<TextBlock
Grid.Column="1"
VerticalAlignment="Center"
FontSize="10"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="{x:Bind ClipboardItem.Content, Mode=OneWay}"
TextWrapping="NoWrap" />
</Grid>
<!-- Text preview -->
<TextBlock
Margin="8,0,0,0"

View File

@@ -38,9 +38,11 @@ namespace AdvancedPaste.Controls
public bool HasImage => ContentImage is not null;
public bool HasText => !string.IsNullOrEmpty(ContentText) && !HasImage;
public bool HasText => !string.IsNullOrEmpty(ContentText) && !HasImage && !HasColor;
public bool HasGlyph => !HasImage && !HasText && !string.IsNullOrEmpty(IconGlyph);
public bool HasGlyph => !HasImage && !HasText && !HasColor && !string.IsNullOrEmpty(IconGlyph);
public bool HasColor => ClipboardItemHelper.IsRgbHexColor(ContentText);
public ClipboardHistoryItemPreviewControl()
{

View File

@@ -0,0 +1,39 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace AdvancedPaste.Converters
{
public static class HexColorConverterHelper
{
public static Windows.UI.Color? ConvertHexColorToRgb(string hexColor)
{
try
{
// Remove # if present
var cleanHex = hexColor.TrimStart('#');
// Expand 3-digit hex to 6-digit (#ABC -> #AABBCC)
if (cleanHex.Length == 3)
{
cleanHex = $"{cleanHex[0]}{cleanHex[0]}{cleanHex[1]}{cleanHex[1]}{cleanHex[2]}{cleanHex[2]}";
}
if (cleanHex.Length == 6)
{
var r = System.Convert.ToByte(cleanHex.Substring(0, 2), 16);
var g = System.Convert.ToByte(cleanHex.Substring(2, 2), 16);
var b = System.Convert.ToByte(cleanHex.Substring(4, 2), 16);
return Windows.UI.Color.FromArgb(255, r, g, b);
}
}
catch
{
// Invalid color format - return null
}
return null;
}
}
}

View File

@@ -0,0 +1,28 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Media;
namespace AdvancedPaste.Converters
{
public sealed partial class HexColorToBrushConverter : IValueConverter
{
public object ConvertBack(object value, Type targetType, object parameter, string language)
=> throw new NotSupportedException();
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value is not string hexColor || string.IsNullOrWhiteSpace(hexColor))
{
return null;
}
Windows.UI.Color? color = HexColorConverterHelper.ConvertHexColorToRgb(hexColor);
return color != null ? new SolidColorBrush((Windows.UI.Color)color) : null;
}
}
}

View File

@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using AdvancedPaste.Models;
using Microsoft.UI.Xaml.Media.Imaging;
@@ -10,8 +11,11 @@ using Windows.ApplicationModel.DataTransfer;
namespace AdvancedPaste.Helpers
{
internal static class ClipboardItemHelper
internal static partial class ClipboardItemHelper
{
// Compiled regex for better performance when checking multiple clipboard items
private static readonly Regex HexColorRegex = HexColorCompiledRegex();
/// <summary>
/// Creates a ClipboardItem from current clipboard data.
/// </summary>
@@ -55,6 +59,31 @@ namespace AdvancedPaste.Helpers
return clipboardItem;
}
/// <summary>
/// Checks if text is a valid RGB hex color (e.g., #FFBFAB or #fff).
/// </summary>
public static bool IsRgbHexColor(string text)
{
if (text == null)
{
return false;
}
string trimmedText = text.Trim();
if (trimmedText.Length > 7)
{
return false;
}
if (string.IsNullOrWhiteSpace(trimmedText))
{
return false;
}
// Match #RGB or #RRGGBB format (case-insensitive)
return HexColorRegex.IsMatch(trimmedText);
}
/// <summary>
/// Creates a BitmapImage from clipboard data.
/// </summary>
@@ -80,5 +109,8 @@ namespace AdvancedPaste.Helpers
return null;
}
[GeneratedRegex(@"^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$")]
private static partial Regex HexColorCompiledRegex();
}
}

View File

@@ -62,7 +62,7 @@ namespace Hosts.Settings
public UserSettings()
{
_settingsUtils = new SettingsUtils();
_settingsUtils = SettingsUtils.Default;
var defaultSettings = new HostsProperties();
ShowStartupWarning = defaultSettings.ShowStartupWarning;
LoopbackDuplicates = defaultSettings.LoopbackDuplicates;

View File

@@ -1,14 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
<PropertyGroup Label="NuGet">
<!-- Tell NuGet this is PackageReference style -->
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<!-- Tell NuGet we're a native project -->
<NuGetTargetMoniker>native,Version=v0.0</NuGetTargetMoniker>
<!-- Tell NuGet we target Windows (use your existing WindowsTargetPlatformVersion) -->
<NuGetTargetPlatformIdentifier>Windows</NuGetTargetPlatformIdentifier>
<NuGetTargetPlatformVersion>$(WindowsTargetPlatformVersion)</NuGetTargetPlatformVersion>
</PropertyGroup>
<PropertyGroup Label="Globals">
<CppWinRTOptimized>true</CppWinRTOptimized>
<CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge>
@@ -31,6 +33,11 @@
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.WindowsAppSDK" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.Windows.CppWinRT" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.Windows.ImplementationLibrary" GeneratePathProperty="true" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
@@ -38,7 +45,6 @@
<DesktopCompatible>true</DesktopCompatible>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="..\..\..\..\deps\spdlog.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
@@ -118,9 +124,6 @@
<WarnAsError>true</WarnAsError>
</Midl>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\common\Display\Display.vcxproj">
<Project>{caba8dfb-823b-4bf2-93ac-3f31984150d9}</Project>
@@ -142,42 +145,5 @@
<ResourceCompile Include="PowerToys.MeasureToolCore.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets'))" />
</Target>
<Import Project="..\..\..\..\deps\spdlog.props" />
</Project>

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Web.WebView2" version="1.0.2903.40" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.231216.1" targetFramework="native" />
<package id="Microsoft.Windows.SDK.BuildTools" version="10.0.26100.4188" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Base" version="1.8.250831001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Foundation" version="1.8.250906002" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.WinUI" version="1.8.250906003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Runtime" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.DWrite" version="1.8.25090401" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.InteractiveExperiences" version="1.8.250906004" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Widgets" version="1.8.250904007" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.AI" version="1.8.37" targetFramework="native" />
<package id="Microsoft.Windows.SDK.BuildTools.MSIX" version="1.7.20250829.1" targetFramework="native" />
</packages>

View File

@@ -73,6 +73,13 @@
<ProjectReference Include="..\..\..\common\interop\PowerToys.Interop.vcxproj" />
<ProjectReference Include="..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
<ProjectReference Include="..\..\..\settings-ui\Settings.UI.Library\Settings.UI.Library.csproj" />
<ProjectReference Include="..\MeasureToolCore\PowerToys.MeasureToolCore.vcxproj" />
<ProjectReference Include="..\MeasureToolCore\PowerToys.MeasureToolCore.vcxproj">
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<BuildProject>true</BuildProject>
</ProjectReference>
<CsWinRTInputs Include="$(OutputPath)\PowerToys.MeasureToolCore.winmd" />
<None Include="$(OutputPath)\PowerToys.MeasureToolCore.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@@ -11,7 +11,7 @@ namespace MeasureToolUI
{
public sealed class Settings
{
private static readonly SettingsUtils ModuleSettings = new();
private static readonly SettingsUtils ModuleSettings = SettingsUtils.Default;
public MeasureToolMeasureStyle DefaultMeasureStyle
{

View File

@@ -1,13 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
<PropertyGroup Label="NuGet">
<!-- Tell NuGet this is PackageReference style -->
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<!-- Tell NuGet we're a native project -->
<NuGetTargetMoniker>native,Version=v0.0</NuGetTargetMoniker>
<!-- Tell NuGet we target Windows (use your existing WindowsTargetPlatformVersion) -->
<NuGetTargetPlatformIdentifier>Windows</NuGetTargetPlatformIdentifier>
<NuGetTargetPlatformVersion>$(WindowsTargetPlatformVersion)</NuGetTargetPlatformVersion>
</PropertyGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{e94fd11c-0591-456f-899f-efc0ca548336}</ProjectGuid>
@@ -20,9 +23,12 @@
<WindowsAppSdkBootstrapInitialize>false</WindowsAppSdkBootstrapInitialize>
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
<WindowsAppSDKVerifyTransitiveDependencies>false</WindowsAppSDKVerifyTransitiveDependencies>
<!-- Force NuGet to treat this project strictly as packages.config style -->
<RestoreProjectStyle>packages.config</RestoreProjectStyle>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.WindowsAppSDK" GeneratePathProperty="true"/>
<PackageReference Include="Microsoft.WindowsAppSDK.Foundation" GeneratePathProperty="true"/>
<PackageReference Include="Microsoft.Windows.CppWinRT" GeneratePathProperty="true"/>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
@@ -127,18 +133,18 @@
<ItemGroup>
<ResourceCompile Include="FindMyMouse.rc" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<!-- Deduplicate WindowsAppRuntimeAutoInitializer.cpp (added twice via transitive imports causing LNK4042). Remove all then add exactly once. -->
<ItemGroup Condition="'$(PkgMicrosoft_WindowsAppSDK)'!=''">
<!-- Remove any transitive inclusion first -->
<ClCompile Remove="$(PkgMicrosoft_WindowsAppSDK)\include\WindowsAppRuntimeAutoInitializer.cpp" />
<!-- Re-add once, but disable PCH because the SDK file doesn't include our pch.h -->
<ClCompile Include="$(PkgMicrosoft_WindowsAppSDK)\include\WindowsAppRuntimeAutoInitializer.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Target Name="FixWinAppSDKAutoInitializer" BeforeTargets="ClCompile" AfterTargets="WindowsAppRuntimeAutoInitializer">
<ItemGroup>
<!-- Remove ALL injected versions of the file -->
<ClCompile Remove="@(ClCompile)" Condition="'%(Filename)' == 'WindowsAppRuntimeAutoInitializer'" />
<!-- Add ONE copy back manually -->
<ClCompile Include="$(PkgMicrosoft_WindowsAppSDK_Foundation)\include\WindowsAppRuntimeAutoInitializer.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
</ItemGroup>
</Target>
<Target Name="RemoveManagedWebView2CoreFromNativeOutDir" AfterTargets="Build">
<ItemGroup>
<_ToDelete Include="$(OutDir)Microsoft.Web.WebView2.Core.dll" />
@@ -148,38 +154,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Import Project="..\..\..\..\deps\spdlog.props" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.Windows.CppWinRT.2.0.240111.5\\build\\native\\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.Windows.CppWinRT.2.0.240111.5\\build\\native\\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.Windows.CppWinRT.2.0.240111.5\\build\\native\\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.Windows.CppWinRT.2.0.240111.5\\build\\native\\Microsoft.Windows.CppWinRT.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.Web.WebView2.1.0.2903.40\\build\\native\\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.Web.WebView2.1.0.2903.40\\build\\native\\Microsoft.Web.WebView2.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Base.1.8.250831001\\build\\native\\Microsoft.WindowsAppSDK.Base.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Base.1.8.250831001\\build\\native\\Microsoft.WindowsAppSDK.Base.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Base.1.8.250831001\\build\\native\\Microsoft.WindowsAppSDK.Base.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Base.1.8.250831001\\build\\native\\Microsoft.WindowsAppSDK.Base.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\\build\\native\\Microsoft.WindowsAppSDK.Foundation.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\\build\\native\\Microsoft.WindowsAppSDK.Foundation.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\\build\\native\\Microsoft.WindowsAppSDK.Foundation.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\\build\\native\\Microsoft.WindowsAppSDK.Foundation.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\\build\\native\\Microsoft.WindowsAppSDK.WinUI.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\\build\\native\\Microsoft.WindowsAppSDK.WinUI.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\\build\\native\\Microsoft.WindowsAppSDK.WinUI.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\\build\\native\\Microsoft.WindowsAppSDK.WinUI.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.Runtime.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.Runtime.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.Runtime.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.Runtime.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\\build\\Microsoft.WindowsAppSDK.DWrite.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\\build\\Microsoft.WindowsAppSDK.DWrite.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\\build\\Microsoft.WindowsAppSDK.DWrite.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\\build\\Microsoft.WindowsAppSDK.DWrite.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\\build\\native\\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\\build\\native\\Microsoft.WindowsAppSDK.InteractiveExperiences.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\\build\\native\\Microsoft.WindowsAppSDK.InteractiveExperiences.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\\build\\native\\Microsoft.WindowsAppSDK.InteractiveExperiences.targets'))" />
</Target>
</Project>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Base" version="1.8.250831001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Foundation" version="1.8.250906002" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.WinUI" version="1.8.250906003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Runtime" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.DWrite" version="1.8.25090401" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.InteractiveExperiences" version="1.8.250906004" targetFramework="native" />
<package id="Microsoft.Web.WebView2" version="1.0.2903.40" targetFramework="native" />
</packages>

View File

@@ -53,7 +53,7 @@ internal sealed class SettingsHelper
lock (this.LockObject)
{
{
var settingsUtils = new SettingsUtils();
var settingsUtils = SettingsUtils.Default;
// set this to 1 to disable retries
var remainingRetries = 5;

View File

@@ -1,248 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// <summary>
// Encrypt/decrypt implementation.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
using System;
using System.Collections.Concurrent;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Threading.Tasks;
using MouseWithoutBorders.Core;
namespace MouseWithoutBorders
{
internal partial class Common
{
#pragma warning disable SYSLIB0021
private static AesCryptoServiceProvider symAl;
#pragma warning restore SYSLIB0021
#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter
internal static string myKey;
#pragma warning restore SA1307
private static uint magicNumber;
private static Random ran = new(); // Used for non encryption related functionality.
internal const int SymAlBlockSize = 16;
/// <summary>
/// This is used for the first encryption block, the following blocks will be combined with the cipher text of the previous block.
/// Thus identical blocks in the socket stream would be encrypted to different cipher text blocks.
/// The first block is a handshake one containing random data.
/// Related Unit Test: TestEncryptDecrypt
/// </summary>
internal static readonly string InitialIV = ulong.MaxValue.ToString(CultureInfo.InvariantCulture);
internal static Random Ran
{
get => Common.ran ??= new Random();
set => Common.ran = value;
}
internal static uint MagicNumber
{
get => Common.magicNumber;
set => Common.magicNumber = value;
}
internal static string MyKey
{
get => Common.myKey;
set
{
if (Common.myKey != value)
{
Common.myKey = value;
_ = Task.Factory.StartNew(
() => Common.GenLegalKey(),
System.Threading.CancellationToken.None,
TaskCreationOptions.None,
TaskScheduler.Default); // Cache the key to improve UX.
}
}
}
internal static string KeyDisplayedText(string key)
{
string displayedValue = string.Empty;
int i = 0;
do
{
int length = Math.Min(4, key.Length - i);
displayedValue += string.Concat(key.AsSpan(i, length), " ");
i += 4;
}
while (i < key.Length - 1);
return displayedValue.Trim();
}
internal static bool GeneratedKey { get; set; }
internal static bool KeyCorrupted { get; set; }
internal static void InitEncryption()
{
try
{
if (symAl == null)
{
#pragma warning disable SYSLIB0021 // No proper replacement for now
symAl = new AesCryptoServiceProvider();
#pragma warning restore SYSLIB0021
symAl.KeySize = 256;
symAl.BlockSize = SymAlBlockSize * 8;
symAl.Padding = PaddingMode.Zeros;
symAl.Mode = CipherMode.CBC;
symAl.GenerateIV();
}
}
catch (Exception e)
{
Logger.Log(e);
}
}
private static readonly ConcurrentDictionary<string, byte[]> LegalKeyDictionary = new(StringComparer.OrdinalIgnoreCase);
internal static byte[] GenLegalKey()
{
byte[] rv;
string myKey = Common.MyKey;
if (!LegalKeyDictionary.TryGetValue(myKey, out byte[] value))
{
Rfc2898DeriveBytes key = new(
myKey,
Common.GetBytesU(InitialIV),
50000,
HashAlgorithmName.SHA512);
rv = key.GetBytes(32);
_ = LegalKeyDictionary.AddOrUpdate(myKey, rv, (k, v) => rv);
}
else
{
rv = value;
}
return rv;
}
private static byte[] GenLegalIV()
{
string st = InitialIV;
int ivLength = symAl.IV.Length;
if (st.Length > ivLength)
{
st = st[..ivLength];
}
else if (st.Length < ivLength)
{
st = st.PadRight(ivLength, ' ');
}
return GetBytes(st);
}
internal static Stream GetEncryptedStream(Stream encryptedStream)
{
ICryptoTransform encryptor;
encryptor = symAl.CreateEncryptor(GenLegalKey(), GenLegalIV());
return new CryptoStream(encryptedStream, encryptor, CryptoStreamMode.Write);
}
internal static Stream GetDecryptedStream(Stream encryptedStream)
{
ICryptoTransform decryptor;
decryptor = symAl.CreateDecryptor(GenLegalKey(), GenLegalIV());
return new CryptoStream(encryptedStream, decryptor, CryptoStreamMode.Read);
}
internal static uint Get24BitHash(string st)
{
if (string.IsNullOrEmpty(st))
{
return 0;
}
byte[] bytes = new byte[PACKAGE_SIZE];
for (int i = 0; i < PACKAGE_SIZE; i++)
{
if (i < st.Length)
{
bytes[i] = (byte)st[i];
}
}
var hash = SHA512.Create();
byte[] hashValue = hash.ComputeHash(bytes);
for (int i = 0; i < 50000; i++)
{
hashValue = hash.ComputeHash(hashValue);
}
Logger.LogDebug(string.Format(CultureInfo.CurrentCulture, "magic: {0},{1},{2}", hashValue[0], hashValue[1], hashValue[^1]));
hash.Clear();
return (uint)((hashValue[0] << 23) + (hashValue[1] << 16) + (hashValue[^1] << 8) + hashValue[2]);
}
internal static string GetDebugInfo(string st)
{
return string.IsNullOrEmpty(st) ? st : ((byte)(Common.GetBytesU(st).Sum(value => value) % 256)).ToString(CultureInfo.InvariantCulture);
}
internal static string CreateDefaultKey()
{
return CreateRandomKey();
}
private const int PW_LENGTH = 16;
public static string CreateRandomKey()
{
// Not including characters like "'`O0& since they are confusing to users.
string[] chars = new[] { "abcdefghjkmnpqrstuvxyz", "ABCDEFGHJKMNPQRSTUVXYZ", "123456789", "~!@#$%^*()_-+=:;<,>.?/\\|[]" };
char[][] charactersUsedForKey = chars.Select(charset => Enumerable.Range(0, charset.Length - 1).Select(i => charset[i]).ToArray()).ToArray();
byte[] randomData = new byte[1];
string key = string.Empty;
do
{
foreach (string set in chars)
{
randomData = RandomNumberGenerator.GetBytes(1);
key += set[randomData[0] % set.Length];
if (key.Length >= PW_LENGTH)
{
break;
}
}
}
while (key.Length < PW_LENGTH);
return key;
}
internal static bool IsKeyValid(string key, out string error)
{
error = string.IsNullOrEmpty(key) || key.Length < 16
? "Key must have at least 16 characters in length (spaces are discarded). Key must be auto generated in one of the machines."
: null;
return error == null;
}
}
}

View File

@@ -1,262 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// <summary>
// Package format/conversion.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
// In X64, we are WOW
[module: SuppressMessage("Microsoft.Portability", "CA1900:ValueTypeFieldsShouldBePortable", Scope = "type", Target = "MouseWithoutBorders.DATA", Justification = "Dotnet port with style preservation")]
namespace MouseWithoutBorders
{
internal enum PackageType// : int
{
// Search for PACKAGE_TYPE_RELATED before changing these!
Invalid = 0xFF,
Error = 0xFE,
Hi = 2,
Hello = 3,
ByeBye = 4,
Heartbeat = 20,
Awake = 21,
HideMouse = 50,
Heartbeat_ex = 51,
Heartbeat_ex_l2 = 52,
Heartbeat_ex_l3 = 53,
Clipboard = 69,
ClipboardDragDrop = 70,
ClipboardDragDropEnd = 71,
ExplorerDragDrop = 72,
ClipboardCapture = 73,
CaptureScreenCommand = 74,
ClipboardDragDropOperation = 75,
ClipboardDataEnd = 76,
MachineSwitched = 77,
ClipboardAsk = 78,
ClipboardPush = 79,
NextMachine = 121,
Keyboard = 122,
Mouse = 123,
ClipboardText = 124,
ClipboardImage = 125,
Handshake = 126,
HandshakeAck = 127,
Matrix = 128,
MatrixSwapFlag = 2,
MatrixTwoRowFlag = 4,
}
internal struct PackageMonitor
{
internal ulong Keyboard;
internal ulong Mouse;
internal ulong Heartbeat;
internal ulong ByeBye;
internal ulong Hello;
internal ulong Matrix;
internal ulong ClipboardText;
internal ulong ClipboardImage;
internal ulong Clipboard;
internal ulong ClipboardDragDrop;
internal ulong ClipboardDragDropEnd;
internal ulong ClipboardAsk;
internal ulong ExplorerDragDrop;
internal ulong Nil;
internal PackageMonitor(ulong value)
{
ClipboardDragDrop = ClipboardDragDropEnd = ExplorerDragDrop =
Keyboard = Mouse = Heartbeat = ByeBye = Hello = Clipboard =
Matrix = ClipboardImage = ClipboardText = Nil = ClipboardAsk = value;
}
}
internal enum ID : uint
{
NONE = 0,
ALL = 255,
}
internal enum ClipboardPostAction : uint
{
Other = 0,
Desktop = 1,
Mspaint = 2,
}
[StructLayout(LayoutKind.Sequential)]
internal struct KEYBDDATA
{
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Same name as in winAPI")]
internal int wVk;
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Same name as in winAPI")]
internal int dwFlags;
}
[StructLayout(LayoutKind.Sequential)]
internal struct MOUSEDATA
{
internal int X;
internal int Y;
internal int WheelDelta;
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Same name as in winAPI")]
internal int dwFlags;
}
// The beauty of "union" in C#
[StructLayout(LayoutKind.Explicit)]
internal class DATA
{
[FieldOffset(0)]
internal PackageType Type; // 4 (first byte = package type, 1 = checksum, 2+3 = magic no.)
[FieldOffset(sizeof(PackageType))]
internal int Id; // 4
[FieldOffset(sizeof(PackageType) + sizeof(uint))]
internal ID Src; // 4
[FieldOffset(sizeof(PackageType) + (2 * sizeof(uint)))]
internal ID Des; // 4
[FieldOffset(sizeof(PackageType) + (3 * sizeof(uint)))]
internal long DateTime;
[FieldOffset(sizeof(PackageType) + (3 * sizeof(uint)) + sizeof(long))]
internal KEYBDDATA Kd;
[FieldOffset(sizeof(PackageType) + (3 * sizeof(uint)))]
internal MOUSEDATA Md;
[FieldOffset(sizeof(PackageType) + (3 * sizeof(uint)))]
internal ID Machine1;
[FieldOffset(sizeof(PackageType) + (4 * sizeof(uint)))]
internal ID Machine2;
[FieldOffset(sizeof(PackageType) + (5 * sizeof(uint)))]
internal ID Machine3;
[FieldOffset(sizeof(PackageType) + (6 * sizeof(uint)))]
internal ID Machine4;
[FieldOffset(sizeof(PackageType) + (3 * sizeof(uint)))]
internal ClipboardPostAction PostAction;
[FieldOffset(sizeof(PackageType) + (7 * sizeof(uint)))]
private long machineNameP1;
[FieldOffset(sizeof(PackageType) + (7 * sizeof(uint)) + sizeof(long))]
private long machineNameP2;
[FieldOffset(sizeof(PackageType) + (7 * sizeof(uint)) + (2 * sizeof(long)))]
private long machineNameP3;
[FieldOffset(sizeof(PackageType) + (7 * sizeof(uint)) + (3 * sizeof(long)))]
private long machineNameP4;
internal string MachineName
{
get
{
string name = Common.GetString(BitConverter.GetBytes(machineNameP1))
+ Common.GetString(BitConverter.GetBytes(machineNameP2))
+ Common.GetString(BitConverter.GetBytes(machineNameP3))
+ Common.GetString(BitConverter.GetBytes(machineNameP4));
return name.Trim();
}
set
{
byte[] machineName = Common.GetBytes(value.PadRight(32, ' '));
machineNameP1 = BitConverter.ToInt64(machineName, 0);
machineNameP2 = BitConverter.ToInt64(machineName, 8);
machineNameP3 = BitConverter.ToInt64(machineName, 16);
machineNameP4 = BitConverter.ToInt64(machineName, 24);
}
}
public DATA()
{
}
public DATA(byte[] initialData)
{
Bytes = initialData;
}
internal byte[] Bytes
{
get
{
byte[] buf = new byte[IsBigPackage ? Common.PACKAGE_SIZE_EX : Common.PACKAGE_SIZE];
Array.Copy(StructToBytes(this), buf, IsBigPackage ? Common.PACKAGE_SIZE_EX : Common.PACKAGE_SIZE);
return buf;
}
set
{
Debug.Assert(value.Length <= Common.PACKAGE_SIZE_EX, "Length > package size");
byte[] buf = new byte[Common.PACKAGE_SIZE_EX];
Array.Copy(value, buf, value.Length);
BytesToStruct(buf, this);
}
}
internal bool IsBigPackage
{
get => Type == 0
? throw new InvalidOperationException("Package type not set.")
: Type switch
{
PackageType.Hello or PackageType.Awake or PackageType.Heartbeat or PackageType.Heartbeat_ex or PackageType.Handshake or PackageType.HandshakeAck or PackageType.ClipboardPush or PackageType.Clipboard or PackageType.ClipboardAsk or PackageType.ClipboardImage or PackageType.ClipboardText or PackageType.ClipboardDataEnd => true,
_ => (Type & PackageType.Matrix) == PackageType.Matrix,
};
}
private byte[] StructToBytes(object structObject)
{
byte[] bytes = new byte[Common.PACKAGE_SIZE_EX];
GCHandle bHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
Marshal.StructureToPtr(structObject, Marshal.UnsafeAddrOfPinnedArrayElement(bytes, 0), false);
bHandle.Free();
return bytes;
}
private void BytesToStruct(byte[] value, object structObject)
{
GCHandle bHandle = GCHandle.Alloc(value, GCHandleType.Pinned);
Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(value, 0), structObject);
bHandle.Free();
}
}
internal partial class Common
{
internal const byte PACKAGE_SIZE = 32;
internal const byte PACKAGE_SIZE_EX = 64;
internal const byte WP_PACKAGE_SIZE = 6;
internal static PackageMonitor PackageSent;
internal static PackageMonitor PackageReceived;
internal static int PackageID;
}
}

View File

@@ -1,33 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using ManagedCommon;
using Microsoft.PowerToys.Telemetry;
using MouseWithoutBorders.Class;
using Logger = MouseWithoutBorders.Core.Logger;
namespace MouseWithoutBorders
{
internal class ShutdownWithPowerToys
{
public static void WaitForPowerToysRunner(ETWTrace etwTrace)
{
try
{
RunnerHelper.WaitForPowerToysRunnerExitFallback(() =>
{
etwTrace?.Dispose();
Common.MainForm.Quit(true, false);
});
}
catch (Exception e)
{
Logger.Log(e);
}
}
}
}

View File

@@ -1,131 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// <summary>
// Virtual key constants.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
using System;
namespace MouseWithoutBorders
{
internal enum VK : ushort
{
CAPITAL = 0x14,
NUMLOCK = 0x90,
SHIFT = 0x10,
CONTROL = 0x11,
MENU = 0x12,
ESCAPE = 0x1B,
BACK = 0x08,
TAB = 0x09,
RETURN = 0x0D,
PRIOR = 0x21,
NEXT = 0x22,
END = 0x23,
HOME = 0x24,
LEFT = 0x25,
UP = 0x26,
RIGHT = 0x27,
DOWN = 0x28,
SELECT = 0x29,
PRINT = 0x2A,
EXECUTE = 0x2B,
SNAPSHOT = 0x2C,
INSERT = 0x2D,
DELETE = 0x2E,
HELP = 0x2F,
NUMPAD0 = 0x60,
NUMPAD1 = 0x61,
NUMPAD2 = 0x62,
NUMPAD3 = 0x63,
NUMPAD4 = 0x64,
NUMPAD5 = 0x65,
NUMPAD6 = 0x66,
NUMPAD7 = 0x67,
NUMPAD8 = 0x68,
NUMPAD9 = 0x69,
MULTIPLY = 0x6A,
ADD = 0x6B,
SEPARATOR = 0x6C,
SUBTRACT = 0x6D,
DECIMAL = 0x6E,
DIVIDE = 0x6F,
F1 = 0x70,
F2 = 0x71,
F3 = 0x72,
F4 = 0x73,
F5 = 0x74,
F6 = 0x75,
F7 = 0x76,
F8 = 0x77,
F9 = 0x78,
F10 = 0x79,
F11 = 0x7A,
F12 = 0x7B,
OEM_1 = 0xBA,
OEM_PLUS = 0xBB,
OEM_COMMA = 0xBC,
OEM_MINUS = 0xBD,
OEM_PERIOD = 0xBE,
OEM_2 = 0xBF,
OEM_3 = 0xC0,
MEDIA_NEXT_TRACK = 0xB0,
MEDIA_PREV_TRACK = 0xB1,
MEDIA_STOP = 0xB2,
MEDIA_PLAY_PAUSE = 0xB3,
LWIN = 0x5B,
RWIN = 0x5C,
LSHIFT = 0xA0,
RSHIFT = 0xA1,
LCONTROL = 0xA2,
RCONTROL = 0xA3,
LMENU = 0xA4,
RMENU = 0xA5,
}
internal partial class Common
{
internal const ushort KEYEVENTF_KEYDOWN = 0x0001;
internal const ushort KEYEVENTF_KEYUP = 0x0002;
internal const int WH_MOUSE = 7;
internal const int WH_KEYBOARD = 2;
internal const int WH_MOUSE_LL = 14;
internal const int WH_KEYBOARD_LL = 13;
internal const int WM_MOUSEMOVE = 0x200;
internal const int WM_LBUTTONDOWN = 0x201;
internal const int WM_RBUTTONDOWN = 0x204;
internal const int WM_MBUTTONDOWN = 0x207;
internal const int WM_XBUTTONDOWN = 0x20B;
internal const int WM_LBUTTONUP = 0x202;
internal const int WM_RBUTTONUP = 0x205;
internal const int WM_MBUTTONUP = 0x208;
internal const int WM_XBUTTONUP = 0x20C;
internal const int WM_LBUTTONDBLCLK = 0x203;
internal const int WM_RBUTTONDBLCLK = 0x206;
internal const int WM_MBUTTONDBLCLK = 0x209;
internal const int WM_MOUSEWHEEL = 0x020A;
internal const int WM_MOUSEHWHEEL = 0x020E;
internal const int WM_KEYDOWN = 0x100;
internal const int WM_KEYUP = 0x101;
internal const int WM_SYSKEYDOWN = 0x104;
internal const int WM_SYSKEYUP = 0x105;
[Flags]
internal enum LLKHF
{
EXTENDED = 0x01,
INJECTED = 0x10,
ALTDOWN = 0x20,
UP = 0x80,
}
}
}

View File

@@ -1,363 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
// <summary>
// Screen/Desktop helper functions.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
using MouseWithoutBorders.Class;
using MouseWithoutBorders.Core;
using Thread = MouseWithoutBorders.Core.Thread;
namespace MouseWithoutBorders
{
// Desktops, and GetScreenConfig routines
internal partial class Common
{
private static MyRectangle newDesktopBounds;
private static MyRectangle newPrimaryScreenBounds;
private static string activeDesktop;
internal static string ActiveDesktop => Common.activeDesktop;
internal static void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e)
{
GetScreenConfig();
}
internal static readonly List<Point> SensitivePoints = new();
private static bool MonitorEnumProc(IntPtr hMonitor, IntPtr hdcMonitor, ref NativeMethods.RECT lprcMonitor, IntPtr dwData)
{
// lprcMonitor is wrong!!! => using GetMonitorInfo(...)
// Log(String.Format( CultureInfo.CurrentCulture,"MONITOR: l{0}, t{1}, r{2}, b{3}", lprcMonitor.Left, lprcMonitor.Top, lprcMonitor.Right, lprcMonitor.Bottom));
NativeMethods.MonitorInfoEx mi = default;
mi.cbSize = Marshal.SizeOf(mi);
_ = NativeMethods.GetMonitorInfo(hMonitor, ref mi);
try
{
// For logging only
_ = NativeMethods.GetDpiForMonitor(hMonitor, 0, out uint dpiX, out uint dpiY);
Logger.Log(string.Format(CultureInfo.CurrentCulture, "MONITOR: ({0}, {1}, {2}, {3}). DPI: ({4}, {5})", mi.rcMonitor.Left, mi.rcMonitor.Top, mi.rcMonitor.Right, mi.rcMonitor.Bottom, dpiX, dpiY));
}
catch (DllNotFoundException)
{
Logger.Log("GetDpiForMonitor is unsupported in Windows 7 and lower.");
}
catch (EntryPointNotFoundException)
{
Logger.Log("GetDpiForMonitor is unsupported in Windows 7 and lower.");
}
catch (Exception e)
{
Logger.Log(e);
}
if (mi.rcMonitor.Left == 0 && mi.rcMonitor.Top == 0 && mi.rcMonitor.Right != 0 && mi.rcMonitor.Bottom != 0)
{
// Primary screen
_ = Interlocked.Exchange(ref screenWidth, mi.rcMonitor.Right - mi.rcMonitor.Left);
_ = Interlocked.Exchange(ref screenHeight, mi.rcMonitor.Bottom - mi.rcMonitor.Top);
newPrimaryScreenBounds.Left = mi.rcMonitor.Left;
newPrimaryScreenBounds.Top = mi.rcMonitor.Top;
newPrimaryScreenBounds.Right = mi.rcMonitor.Right;
newPrimaryScreenBounds.Bottom = mi.rcMonitor.Bottom;
}
else
{
if (mi.rcMonitor.Left < newDesktopBounds.Left)
{
newDesktopBounds.Left = mi.rcMonitor.Left;
}
if (mi.rcMonitor.Top < newDesktopBounds.Top)
{
newDesktopBounds.Top = mi.rcMonitor.Top;
}
if (mi.rcMonitor.Right > newDesktopBounds.Right)
{
newDesktopBounds.Right = mi.rcMonitor.Right;
}
if (mi.rcMonitor.Bottom > newDesktopBounds.Bottom)
{
newDesktopBounds.Bottom = mi.rcMonitor.Bottom;
}
}
lock (SensitivePoints)
{
SensitivePoints.Add(new Point(mi.rcMonitor.Left, mi.rcMonitor.Top));
SensitivePoints.Add(new Point(mi.rcMonitor.Right, mi.rcMonitor.Top));
SensitivePoints.Add(new Point(mi.rcMonitor.Right, mi.rcMonitor.Bottom));
SensitivePoints.Add(new Point(mi.rcMonitor.Left, mi.rcMonitor.Bottom));
}
return true;
}
internal static void GetScreenConfig()
{
try
{
Logger.LogDebug("==================== GetScreenConfig started");
newDesktopBounds = new MyRectangle();
newPrimaryScreenBounds = new MyRectangle();
newDesktopBounds.Left = newPrimaryScreenBounds.Left = Screen.PrimaryScreen.Bounds.Left;
newDesktopBounds.Top = newPrimaryScreenBounds.Top = Screen.PrimaryScreen.Bounds.Top;
newDesktopBounds.Right = newPrimaryScreenBounds.Right = Screen.PrimaryScreen.Bounds.Right;
newDesktopBounds.Bottom = newPrimaryScreenBounds.Bottom = Screen.PrimaryScreen.Bounds.Bottom;
Logger.Log(string.Format(
CultureInfo.CurrentCulture,
"logon = {0} PrimaryScreenBounds = {1},{2},{3},{4} desktopBounds = {5},{6},{7},{8}",
Common.RunOnLogonDesktop,
Common.newPrimaryScreenBounds.Left,
Common.newPrimaryScreenBounds.Top,
Common.newPrimaryScreenBounds.Right,
Common.newPrimaryScreenBounds.Bottom,
Common.newDesktopBounds.Left,
Common.newDesktopBounds.Top,
Common.newDesktopBounds.Right,
Common.newDesktopBounds.Bottom));
#if USE_MANAGED_ROUTINES
// Managed routines do not work well when running on secure desktop:(
screenWidth = Screen.PrimaryScreen.Bounds.Width;
screenHeight = Screen.PrimaryScreen.Bounds.Height;
screenCount = Screen.AllScreens.Length;
for (int i = 0; i < Screen.AllScreens.Length; i++)
{
if (Screen.AllScreens[i].Bounds.Left < desktopBounds.Left) desktopBounds.Left = Screen.AllScreens[i].Bounds.Left;
if (Screen.AllScreens[i].Bounds.Top < desktopBounds.Top) desktopBounds.Top = Screen.AllScreens[i].Bounds.Top;
if (Screen.AllScreens[i].Bounds.Right > desktopBounds.Right) desktopBounds.Right = Screen.AllScreens[i].Bounds.Right;
if (Screen.AllScreens[i].Bounds.Bottom > desktopBounds.Bottom) desktopBounds.Bottom = Screen.AllScreens[i].Bounds.Bottom;
}
#else
lock (SensitivePoints)
{
SensitivePoints.Clear();
}
NativeMethods.EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, MonitorEnumProc, IntPtr.Zero);
// 1000 calls to EnumDisplayMonitors cost a dozen of milliseconds
#endif
Interlocked.Exchange(ref MachineStuff.desktopBounds, newDesktopBounds);
Interlocked.Exchange(ref MachineStuff.primaryScreenBounds, newPrimaryScreenBounds);
Logger.Log(string.Format(
CultureInfo.CurrentCulture,
"logon = {0} PrimaryScreenBounds = {1},{2},{3},{4} desktopBounds = {5},{6},{7},{8}",
Common.RunOnLogonDesktop,
MachineStuff.PrimaryScreenBounds.Left,
MachineStuff.PrimaryScreenBounds.Top,
MachineStuff.PrimaryScreenBounds.Right,
MachineStuff.PrimaryScreenBounds.Bottom,
MachineStuff.DesktopBounds.Left,
MachineStuff.DesktopBounds.Top,
MachineStuff.DesktopBounds.Right,
MachineStuff.DesktopBounds.Bottom));
Logger.Log("==================== GetScreenConfig ended");
}
catch (Exception e)
{
Logger.Log(e);
}
}
#if USING_SCREEN_SAVER_ROUTINES
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int PostMessage(IntPtr hWnd, int wMsg, int wParam, int lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr OpenDesktop(string hDesktop, int Flags, bool Inherit, UInt32 DesiredAccess);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool CloseDesktop(IntPtr hDesktop);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool EnumDesktopWindows( IntPtr hDesktop, EnumDesktopWindowsProc callback, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool SystemParametersInfo(int uAction, int uParam, ref int pvParam, int flags);
private delegate bool EnumDesktopWindowsProc(IntPtr hDesktop, IntPtr lParam);
private const int WM_CLOSE = 16;
private const int SPI_GETSCREENSAVERRUNNING = 114;
internal static bool IsScreenSaverRunning()
{
int isRunning = 0;
SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0,ref isRunning, 0);
return (isRunning != 0);
}
internal static void CloseScreenSaver()
{
IntPtr hDesktop = OpenDesktop("Screen-saver", 0, false, DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS);
if (hDesktop != IntPtr.Zero)
{
LogDebug("Closing screen saver...");
EnumDesktopWindows(hDesktop, new EnumDesktopWindowsProc(CloseScreenSaverFunc), IntPtr.Zero);
CloseDesktop(hDesktop);
}
}
private static bool CloseScreenSaverFunc(IntPtr hWnd, IntPtr lParam)
{
if (IsWindowVisible(hWnd))
{
LogDebug("Posting WM_CLOSE to " + hWnd.ToString(CultureInfo.InvariantCulture));
PostMessage(hWnd, WM_CLOSE, 0, 0);
}
return true;
}
#endif
internal static string GetMyDesktop()
{
byte[] arThreadDesktop = new byte[256];
IntPtr hD = NativeMethods.GetThreadDesktop(NativeMethods.GetCurrentThreadId());
if (hD != IntPtr.Zero)
{
_ = NativeMethods.GetUserObjectInformation(hD, NativeMethods.UOI_NAME, arThreadDesktop, arThreadDesktop.Length, out _);
return GetString(arThreadDesktop).Replace("\0", string.Empty);
}
return string.Empty;
}
internal static string GetInputDesktop()
{
byte[] arInputDesktop = new byte[256];
IntPtr hD = NativeMethods.OpenInputDesktop(0, false, NativeMethods.DESKTOP_READOBJECTS);
if (hD != IntPtr.Zero)
{
_ = NativeMethods.GetUserObjectInformation(hD, NativeMethods.UOI_NAME, arInputDesktop, arInputDesktop.Length, out _);
return GetString(arInputDesktop).Replace("\0", string.Empty);
}
return string.Empty;
}
internal static void StartMMService(string desktopToRunMouseWithoutBordersOn)
{
if (!Common.RunWithNoAdminRight)
{
Logger.LogDebug("*** Starting on active Desktop: " + desktopToRunMouseWithoutBordersOn);
Service.StartMouseWithoutBordersService(desktopToRunMouseWithoutBordersOn);
}
}
internal static void CheckForDesktopSwitchEvent(bool cleanupIfExit)
{
try
{
if (!IsMyDesktopActive() || Common.CurrentProcess.SessionId != NativeMethods.WTSGetActiveConsoleSessionId())
{
Helper.RunDDHelper(true);
int waitCount = 20;
while (NativeMethods.WTSGetActiveConsoleSessionId() == 0xFFFFFFFF && waitCount > 0)
{
waitCount--;
Logger.LogDebug("The session is detached/attached.");
Thread.Sleep(500);
}
string myDesktop = GetMyDesktop();
activeDesktop = GetInputDesktop();
Logger.LogDebug("*** Active Desktop = " + activeDesktop);
Logger.LogDebug("*** My Desktop = " + myDesktop);
if (myDesktop.Equals(activeDesktop, StringComparison.OrdinalIgnoreCase))
{
Logger.LogDebug("*** Active Desktop == My Desktop (TS session)");
}
if (!activeDesktop.Equals("winlogon", StringComparison.OrdinalIgnoreCase) &&
!activeDesktop.Equals("default", StringComparison.OrdinalIgnoreCase) &&
!activeDesktop.Equals("disconnect", StringComparison.OrdinalIgnoreCase))
{
try
{
StartMMService(activeDesktop);
}
catch (Exception e)
{
Logger.Log($"{nameof(CheckForDesktopSwitchEvent)}: {e}");
}
}
else
{
if (!myDesktop.Equals(activeDesktop, StringComparison.OrdinalIgnoreCase))
{
Logger.Log("*** Active Desktop <> My Desktop");
}
uint sid = NativeMethods.WTSGetActiveConsoleSessionId();
if (Process.GetProcessesByName(Common.BinaryName).Any(p => (uint)p.SessionId == sid))
{
Logger.Log("Found MouseWithoutBorders on the active session!");
}
else
{
Logger.Log("MouseWithoutBorders not found on the active session!");
StartMMService(null);
}
}
if (!myDesktop.Equals("winlogon", StringComparison.OrdinalIgnoreCase) &&
!myDesktop.Equals("default", StringComparison.OrdinalIgnoreCase))
{
Logger.LogDebug("*** Desktop inactive, exiting: " + myDesktop);
Setting.Values.LastX = JUST_GOT_BACK_FROM_SCREEN_SAVER;
if (cleanupIfExit)
{
InitAndCleanup.Cleanup();
}
Process.GetCurrentProcess().KillProcess();
}
}
}
catch (Exception e)
{
Logger.Log(e);
}
}
private static Point p;
internal static bool IsMyDesktopActive()
{
return NativeMethods.GetCursorPos(ref p);
}
}
}

View File

@@ -315,7 +315,7 @@ namespace MouseWithoutBorders
if (!acquireMutex)
{
Process[] ps = Process.GetProcessesByName(Common.BinaryName);
Logger.TelemetryLogTrace($"Balance: {socketMutexBalance}, Active: {IsMyDesktopActive()}, Sid/Console: {Process.GetCurrentProcess().SessionId}/{NativeMethods.WTSGetActiveConsoleSessionId()}, Desktop/Input: {GetMyDesktop()}/{GetInputDesktop()}, count: {ps?.Length}.", SeverityLevel.Warning);
Logger.TelemetryLogTrace($"Balance: {socketMutexBalance}, Active: {WinAPI.IsMyDesktopActive()}, Sid/Console: {Process.GetCurrentProcess().SessionId}/{NativeMethods.WTSGetActiveConsoleSessionId()}, Desktop/Input: {WinAPI.GetMyDesktop()}/{WinAPI.GetInputDesktop()}, count: {ps?.Length}.", SeverityLevel.Warning);
}
Logger.LogDebug("SOCKET MUTEX ENDED.");
@@ -358,7 +358,7 @@ namespace MouseWithoutBorders
Logger.TelemetryLogTrace($"[{actionName}] took more than {(long)timeout.TotalSeconds}, restarting the process.", SeverityLevel.Warning, true);
string desktop = Common.GetMyDesktop();
string desktop = WinAPI.GetMyDesktop();
MachineStuff.oneInstanceCheck?.Close();
_ = Process.Start(Application.ExecutablePath, desktop);
Logger.LogDebug($"Started on desktop {desktop}");
@@ -514,7 +514,7 @@ namespace MouseWithoutBorders
internal static void SendHeartBeat(bool initial = false)
{
SendPackage(ID.ALL, initial && Common.GeneratedKey ? PackageType.Heartbeat_ex : PackageType.Heartbeat);
SendPackage(ID.ALL, initial && Encryption.GeneratedKey ? PackageType.Heartbeat_ex : PackageType.Heartbeat);
}
private static long lastSendNextMachine;
@@ -550,7 +550,7 @@ namespace MouseWithoutBorders
internal static void SendAwakeBeat()
{
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && Common.IsMyDesktopActive() &&
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && WinAPI.IsMyDesktopActive() &&
Setting.Values.BlockScreenSaver && lastRealInputEventCount != Event.RealInputEventCount)
{
SendPackage(ID.ALL, PackageType.Awake);
@@ -568,7 +568,7 @@ namespace MouseWithoutBorders
{
if (lastInputEventCount == Event.InputEventCount)
{
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && Common.IsMyDesktopActive())
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && WinAPI.IsMyDesktopActive())
{
PokeMyself();
}
@@ -577,13 +577,13 @@ namespace MouseWithoutBorders
lastInputEventCount = Event.InputEventCount;
}
private static void PokeMyself()
internal static void PokeMyself()
{
int x, y = 0;
for (int i = 0; i < 10; i++)
{
x = Ran.Next(-9, 10);
x = Encryption.Ran.Next(-9, 10);
InputSimulation.MoveMouseRelative(x, y);
Thread.Sleep(50);
InputSimulation.MoveMouseRelative(-x, -y);
@@ -677,7 +677,7 @@ namespace MouseWithoutBorders
{
Common.MMSleep(0.2);
InputSimulation.SendKey(new KEYBDDATA() { wVk = (int)VK.SNAPSHOT });
InputSimulation.SendKey(new KEYBDDATA() { dwFlags = (int)Common.LLKHF.UP, wVk = (int)VK.SNAPSHOT });
InputSimulation.SendKey(new KEYBDDATA() { dwFlags = (int)WM.LLKHF.UP, wVk = (int)VK.SNAPSHOT });
Logger.LogDebug("PrepareScreenCapture: SNAPSHOT simulated.");
@@ -710,7 +710,7 @@ namespace MouseWithoutBorders
"\"" + Environment.ExpandEnvironmentVariables(@"%SystemRoot%\System32\Mspaint.exe") +
"\"",
"\"" + file + "\"",
GetInputDesktop(),
WinAPI.GetInputDesktop(),
1);
// CreateNormalIntegrityProcess(Environment.ExpandEnvironmentVariables(@"%SystemRoot%\System32\Mspaint.exe") +
@@ -919,7 +919,7 @@ namespace MouseWithoutBorders
try
{
data.Id = Interlocked.Increment(ref PackageID);
data.Id = Interlocked.Increment(ref Package.PackageID);
bool updateClientSockets = false;
@@ -999,7 +999,7 @@ namespace MouseWithoutBorders
}
else
{
PackageSent.Nil++;
Package.PackageSent.Nil++;
}
}
@@ -1379,7 +1379,7 @@ namespace MouseWithoutBorders
if (string.IsNullOrEmpty(machine_Name))
{
machine_Name = "RANDOM" + Ran.Next().ToString(CultureInfo.CurrentCulture);
machine_Name = "RANDOM" + Encryption.Ran.Next().ToString(CultureInfo.CurrentCulture);
}
}
@@ -1533,13 +1533,13 @@ namespace MouseWithoutBorders
internal static void SendOrReceiveARandomDataBlockPerInitialIV(Stream st, bool send = true)
{
byte[] ranData = new byte[SymAlBlockSize];
byte[] ranData = new byte[Encryption.SymAlBlockSize];
try
{
if (send)
{
ranData = RandomNumberGenerator.GetBytes(SymAlBlockSize);
ranData = RandomNumberGenerator.GetBytes(Encryption.SymAlBlockSize);
st.Write(ranData, 0, ranData.Length);
}
else

View File

@@ -109,7 +109,7 @@ namespace MouseWithoutBorders.Class
// Install Mouse Hook
mouseHookProcedure = new NativeMethods.HookProc(MouseHookProc);
hMouseHook = NativeMethods.SetWindowsHookEx(
Common.WH_MOUSE_LL,
WM.WH_MOUSE_LL,
mouseHookProcedure,
Marshal.GetHINSTANCE(
Assembly.GetExecutingAssembly().GetModules()[0]),
@@ -126,7 +126,7 @@ namespace MouseWithoutBorders.Class
// Install Keyboard Hook
keyboardHookProcedure = new NativeMethods.HookProc(KeyboardHookProc);
hKeyboardHook = NativeMethods.SetWindowsHookEx(
Common.WH_KEYBOARD_LL,
WM.WH_KEYBOARD_LL,
keyboardHookProcedure,
Marshal.GetHINSTANCE(
Assembly.GetExecutingAssembly().GetModules()[0]),
@@ -233,7 +233,7 @@ namespace MouseWithoutBorders.Class
if (nCode >= 0 && MouseEvent != null)
{
if (wParam == Common.WM_LBUTTONUP && SkipMouseUpCount > 0)
if (wParam == WM.WM_LBUTTONUP && SkipMouseUpCount > 0)
{
Logger.LogDebug($"{nameof(SkipMouseUpCount)}: {SkipMouseUpCount}.");
SkipMouseUpCount--;
@@ -241,7 +241,7 @@ namespace MouseWithoutBorders.Class
return rv;
}
if ((wParam == Common.WM_LBUTTONUP || wParam == Common.WM_LBUTTONDOWN) && SkipMouseUpDown)
if ((wParam == WM.WM_LBUTTONUP || wParam == WM.WM_LBUTTONDOWN) && SkipMouseUpDown)
{
rv = NativeMethods.CallNextHookEx(hMouseHook, nCode, wParam, lParam);
return rv;
@@ -370,7 +370,7 @@ namespace MouseWithoutBorders.Class
private bool ProcessKeyEx(int vkCode, int flags, KEYBDDATA hookCallbackKeybdData)
{
if ((flags & (int)Common.LLKHF.UP) == (int)Common.LLKHF.UP)
if ((flags & (int)WM.LLKHF.UP) == (int)WM.LLKHF.UP)
{
EasyMouseKeyDown = false;
@@ -553,7 +553,7 @@ namespace MouseWithoutBorders.Class
KeyboardEvent(hookCallbackKeybdData);
}
hookCallbackKeybdData.dwFlags |= (int)Common.LLKHF.UP;
hookCallbackKeybdData.dwFlags |= (int)WM.LLKHF.UP;
foreach (var code in codes)
{

View File

@@ -112,12 +112,12 @@ namespace MouseWithoutBorders.Class
uint scanCode = 0;
// http://msdn.microsoft.com/en-us/library/ms644967(VS.85).aspx
if ((kd.dwFlags & (int)Common.LLKHF.UP) == (int)Common.LLKHF.UP)
if ((kd.dwFlags & (int)WM.LLKHF.UP) == (int)WM.LLKHF.UP)
{
dwFlags = NativeMethods.KEYEVENTF.KEYUP;
}
if ((kd.dwFlags & (int)Common.LLKHF.EXTENDED) == (int)Common.LLKHF.EXTENDED)
if ((kd.dwFlags & (int)WM.LLKHF.EXTENDED) == (int)WM.LLKHF.EXTENDED)
{
dwFlags |= NativeMethods.KEYEVENTF.EXTENDEDKEY;
}
@@ -173,44 +173,44 @@ namespace MouseWithoutBorders.Class
mouse_input.mi.dy = (int)dy;
mouse_input.mi.mouseData = md.WheelDelta;
if (md.dwFlags != Common.WM_MOUSEMOVE)
if (md.dwFlags != WM.WM_MOUSEMOVE)
{
Logger.LogDebug($"InputSimulation.SendMouse: x = {md.X}, y = {md.Y}, WheelDelta = {md.WheelDelta}, dwFlags = {md.dwFlags}.");
}
switch (md.dwFlags)
{
case Common.WM_MOUSEMOVE:
case WM.WM_MOUSEMOVE:
mouse_input.mi.dwFlags |= (int)(NativeMethods.MOUSEEVENTF.MOVE | NativeMethods.MOUSEEVENTF.ABSOLUTE);
break;
case Common.WM_LBUTTONDOWN:
case WM.WM_LBUTTONDOWN:
mouse_input.mi.dwFlags |= (int)NativeMethods.MOUSEEVENTF.LEFTDOWN;
break;
case Common.WM_LBUTTONUP:
case WM.WM_LBUTTONUP:
mouse_input.mi.dwFlags |= (int)NativeMethods.MOUSEEVENTF.LEFTUP;
break;
case Common.WM_RBUTTONDOWN:
case WM.WM_RBUTTONDOWN:
mouse_input.mi.dwFlags |= (int)NativeMethods.MOUSEEVENTF.RIGHTDOWN;
break;
case Common.WM_RBUTTONUP:
case WM.WM_RBUTTONUP:
mouse_input.mi.dwFlags |= (int)NativeMethods.MOUSEEVENTF.RIGHTUP;
break;
case Common.WM_MBUTTONDOWN:
case WM.WM_MBUTTONDOWN:
mouse_input.mi.dwFlags |= (int)NativeMethods.MOUSEEVENTF.MIDDLEDOWN;
break;
case Common.WM_MBUTTONUP:
case WM.WM_MBUTTONUP:
mouse_input.mi.dwFlags |= (int)NativeMethods.MOUSEEVENTF.MIDDLEUP;
break;
case Common.WM_MOUSEWHEEL:
case WM.WM_MOUSEWHEEL:
mouse_input.mi.dwFlags |= (int)NativeMethods.MOUSEEVENTF.WHEEL;
break;
case Common.WM_MOUSEHWHEEL:
case WM.WM_MOUSEHWHEEL:
mouse_input.mi.dwFlags |= (int)NativeMethods.MOUSEEVENTF.HWHEEL;
break;
case Common.WM_XBUTTONUP:
case WM.WM_XBUTTONUP:
mouse_input.mi.dwFlags |= (int)NativeMethods.MOUSEEVENTF.XUP;
break;
case Common.WM_XBUTTONDOWN:
case WM.WM_XBUTTONDOWN:
mouse_input.mi.dwFlags |= (int)NativeMethods.MOUSEEVENTF.XDOWN;
break;
@@ -373,7 +373,7 @@ namespace MouseWithoutBorders.Class
{
eatKey = false;
if ((flags & (int)Common.LLKHF.UP) == (int)Common.LLKHF.UP)
if ((flags & (int)WM.LLKHF.UP) == (int)WM.LLKHF.UP)
{
switch ((VK)vkCode)
{

View File

@@ -143,7 +143,7 @@ namespace MouseWithoutBorders.Class
return;
}
string myDesktop = Common.GetMyDesktop();
string myDesktop = WinAPI.GetMyDesktop();
if (firstArg.Equals("winlogon", StringComparison.OrdinalIgnoreCase))
{
@@ -305,8 +305,8 @@ namespace MouseWithoutBorders.Class
MachineStuff.ClearComputerMatrix();
Setting.Values.MyKey = securityKey;
Common.MyKey = securityKey;
Common.MagicNumber = Common.Get24BitHash(Common.MyKey);
Encryption.MyKey = securityKey;
Encryption.MagicNumber = Encryption.Get24BitHash(Encryption.MyKey);
MachineStuff.MachineMatrix = new string[MachineStuff.MAX_MACHINE] { pcName.Trim().ToUpper(CultureInfo.CurrentCulture), Common.MachineName.Trim(), string.Empty, string.Empty };
string[] machines = MachineStuff.MachineMatrix;
@@ -328,8 +328,8 @@ namespace MouseWithoutBorders.Class
Setting.Values.EasyMouse = (int)EasyMouseOption.Enable;
MachineStuff.ClearComputerMatrix();
Setting.Values.MyKey = Common.MyKey = Common.CreateRandomKey();
Common.GeneratedKey = true;
Setting.Values.MyKey = Encryption.MyKey = Encryption.CreateRandomKey();
Encryption.GeneratedKey = true;
Setting.Values.PauseInstantSaving = false;
Setting.Values.SaveSettings();

View File

@@ -109,9 +109,9 @@ namespace MouseWithoutBorders.Class
var shouldReopenSockets = false;
if (Common.MyKey != _properties.SecurityKey.Value)
if (Encryption.MyKey != _properties.SecurityKey.Value)
{
Common.MyKey = _properties.SecurityKey.Value;
Encryption.MyKey = _properties.SecurityKey.Value;
shouldReopenSockets = true;
}
@@ -192,7 +192,7 @@ namespace MouseWithoutBorders.Class
internal Settings()
{
_settingsUtils = new SettingsUtils();
_settingsUtils = SettingsUtils.Default;
_watcher = SettingsHelper.GetFileWatcher("MouseWithoutBorders", "settings.json", () =>
{
@@ -489,7 +489,7 @@ namespace MouseWithoutBorders.Class
}
else
{
string randomKey = Common.CreateDefaultKey();
string randomKey = Encryption.CreateDefaultKey();
_properties.SecurityKey.Value = randomKey;
return randomKey;
@@ -1055,7 +1055,7 @@ namespace MouseWithoutBorders.Class
if (machineId == 0)
{
var newMachineId = Common.Ran.Next();
var newMachineId = Encryption.Ran.Next();
_properties.MachineID.Value = newMachineId;
machineId = newMachineId;
if (!PauseInstantSaving)

View File

@@ -101,7 +101,7 @@ namespace MouseWithoutBorders.Class
{
if (encryptedStream == null && BackingSocket.Connected)
{
encryptedStream = Common.GetEncryptedStream(new NetworkStream(BackingSocket));
encryptedStream = Encryption.GetEncryptedStream(new NetworkStream(BackingSocket));
Common.SendOrReceiveARandomDataBlockPerInitialIV(encryptedStream);
}
@@ -115,7 +115,7 @@ namespace MouseWithoutBorders.Class
{
if (decryptedStream == null && BackingSocket.Connected)
{
decryptedStream = Common.GetDecryptedStream(new NetworkStream(BackingSocket));
decryptedStream = Encryption.GetDecryptedStream(new NetworkStream(BackingSocket));
Common.SendOrReceiveARandomDataBlockPerInitialIV(decryptedStream, false);
}
@@ -181,7 +181,7 @@ namespace MouseWithoutBorders.Class
Logger.LogDebug("SocketStuff started.");
bASE_PORT = port;
Common.Ran = new Random();
Encryption.Ran = new Random();
Logger.LogDebug("Validating session...");
@@ -221,11 +221,11 @@ namespace MouseWithoutBorders.Class
if (Setting.Values.IsMyKeyRandom)
{
Setting.Values.MyKey = Common.MyKey;
Setting.Values.MyKey = Encryption.MyKey;
}
Common.MagicNumber = Common.Get24BitHash(Common.MyKey);
Common.PackageID = Setting.Values.PackageID;
Encryption.MagicNumber = Encryption.Get24BitHash(Encryption.MyKey);
Package.PackageID = Setting.Values.PackageID;
TcpPort = bASE_PORT;
@@ -242,7 +242,7 @@ namespace MouseWithoutBorders.Class
Logger.TelemetryLogTrace($"{nameof(SocketStuff)}: {e.Message}", SeverityLevel.Warning);
}
Common.GetScreenConfig();
WinAPI.GetScreenConfig();
if (firstRun && Common.RunOnScrSaverDesktop)
{
@@ -305,7 +305,7 @@ namespace MouseWithoutBorders.Class
sleepSecs = 10;
// It is reasonable to give a try on restarting MwB processes in other sessions.
if (restartCount++ < 5 && Common.IsMyDesktopActive() && !Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
if (restartCount++ < 5 && WinAPI.IsMyDesktopActive() && !Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
{
Logger.TelemetryLogTrace("Restarting the service dues to WSAEADDRINUSE.", SeverityLevel.Warning);
Program.StartService();
@@ -361,7 +361,7 @@ namespace MouseWithoutBorders.Class
{
Setting.Values.LastX = Common.LastX;
Setting.Values.LastY = Common.LastY;
Setting.Values.PackageID = Common.PackageID;
Setting.Values.PackageID = Package.PackageID;
// Common.Log("Saving IP: " + Setting.Values.DesMachineID.ToString(CultureInfo.CurrentCulture));
Setting.Values.DesMachineID = (uint)Common.DesMachineID;
@@ -505,10 +505,10 @@ namespace MouseWithoutBorders.Class
throw new ExpectedSocketException(log);
}
bytes[3] = (byte)((Common.MagicNumber >> 24) & 0xFF);
bytes[2] = (byte)((Common.MagicNumber >> 16) & 0xFF);
bytes[3] = (byte)((Encryption.MagicNumber >> 24) & 0xFF);
bytes[2] = (byte)((Encryption.MagicNumber >> 16) & 0xFF);
bytes[1] = 0;
for (int i = 2; i < Common.PACKAGE_SIZE; i++)
for (int i = 2; i < Package.PACKAGE_SIZE; i++)
{
bytes[1] = (byte)(bytes[1] + bytes[i]);
}
@@ -535,13 +535,13 @@ namespace MouseWithoutBorders.Class
magic = (buf[3] << 24) + (buf[2] << 16);
if (magic != (Common.MagicNumber & 0xFFFF0000))
if (magic != (Encryption.MagicNumber & 0xFFFF0000))
{
Logger.Log("Magic number invalid!");
buf[0] = (byte)PackageType.Invalid;
}
for (int i = 2; i < Common.PACKAGE_SIZE; i++)
for (int i = 2; i < Package.PACKAGE_SIZE; i++)
{
checksum = (byte)(checksum + buf[i]);
}
@@ -557,7 +557,7 @@ namespace MouseWithoutBorders.Class
internal static DATA TcpReceiveData(TcpSk tcp, out int bytesReceived)
{
byte[] buf = new byte[Common.PACKAGE_SIZE_EX];
byte[] buf = new byte[Package.PACKAGE_SIZE_EX];
Stream decryptedStream = tcp.DecryptedStream;
if (tcp.BackingSocket == null || !tcp.BackingSocket.Connected || decryptedStream == null)
@@ -571,9 +571,9 @@ namespace MouseWithoutBorders.Class
try
{
bytesReceived = decryptedStream.ReadEx(buf, 0, Common.PACKAGE_SIZE);
bytesReceived = decryptedStream.ReadEx(buf, 0, Package.PACKAGE_SIZE);
if (bytesReceived != Common.PACKAGE_SIZE)
if (bytesReceived != Package.PACKAGE_SIZE)
{
buf[0] = bytesReceived == 0 ? (byte)PackageType.Error : (byte)PackageType.Invalid;
}
@@ -586,9 +586,9 @@ namespace MouseWithoutBorders.Class
if (package.IsBigPackage)
{
bytesReceived = decryptedStream.ReadEx(buf, Common.PACKAGE_SIZE, Common.PACKAGE_SIZE);
bytesReceived = decryptedStream.ReadEx(buf, Package.PACKAGE_SIZE, Package.PACKAGE_SIZE);
if (bytesReceived != Common.PACKAGE_SIZE)
if (bytesReceived != Package.PACKAGE_SIZE)
{
buf[0] = bytesReceived == 0 ? (byte)PackageType.Error : (byte)PackageType.Invalid;
}
@@ -614,28 +614,28 @@ namespace MouseWithoutBorders.Class
switch (type)
{
case PackageType.Keyboard:
Common.PackageSent.Keyboard++;
Package.PackageSent.Keyboard++;
break;
case PackageType.Mouse:
Common.PackageSent.Mouse++;
Package.PackageSent.Mouse++;
break;
case PackageType.Heartbeat:
case PackageType.Heartbeat_ex:
Common.PackageSent.Heartbeat++;
Package.PackageSent.Heartbeat++;
break;
case PackageType.Hello:
Common.PackageSent.Hello++;
Package.PackageSent.Hello++;
break;
case PackageType.ByeBye:
Common.PackageSent.ByeBye++;
Package.PackageSent.ByeBye++;
break;
case PackageType.Matrix:
Common.PackageSent.Matrix++;
Package.PackageSent.Matrix++;
break;
default:
@@ -643,11 +643,11 @@ namespace MouseWithoutBorders.Class
switch (subtype)
{
case (byte)PackageType.ClipboardText:
Common.PackageSent.ClipboardText++;
Package.PackageSent.ClipboardText++;
break;
case (byte)PackageType.ClipboardImage:
Common.PackageSent.ClipboardImage++;
Package.PackageSent.ClipboardImage++;
break;
default:
@@ -1266,7 +1266,7 @@ namespace MouseWithoutBorders.Class
string strIP = string.Empty;
ID remoteID = ID.NONE;
byte[] buf = RandomNumberGenerator.GetBytes(Common.PACKAGE_SIZE_EX);
byte[] buf = RandomNumberGenerator.GetBytes(Package.PACKAGE_SIZE_EX);
d = new DATA(buf);
TcpSk currentTcp = tcp;
@@ -1280,8 +1280,8 @@ namespace MouseWithoutBorders.Class
try
{
currentSocket.SendBufferSize = Common.PACKAGE_SIZE * 10000;
currentSocket.ReceiveBufferSize = Common.PACKAGE_SIZE * 10000;
currentSocket.SendBufferSize = Package.PACKAGE_SIZE * 10000;
currentSocket.ReceiveBufferSize = Package.PACKAGE_SIZE * 10000;
currentSocket.NoDelay = true; // This is very interesting to know:(
currentSocket.SendTimeout = 500;
d.MachineName = Common.MachineName;
@@ -1829,7 +1829,7 @@ namespace MouseWithoutBorders.Class
}
while (rv > 0);
if ((rv = Common.PACKAGE_SIZE - (sentCount % Common.PACKAGE_SIZE)) > 0)
if ((rv = Package.PACKAGE_SIZE - (sentCount % Package.PACKAGE_SIZE)) > 0)
{
Array.Clear(buf, 0, buf.Length);
ecStream.Write(buf, 0, rv);
@@ -1900,7 +1900,7 @@ namespace MouseWithoutBorders.Class
}
while (rv > 0);
if ((rv = sentCount % Common.PACKAGE_SIZE) > 0)
if ((rv = sentCount % Package.PACKAGE_SIZE) > 0)
{
Array.Clear(buf, 0, buf.Length);
ecStream.Write(buf, 0, rv);
@@ -1984,7 +1984,7 @@ namespace MouseWithoutBorders.Class
if (tcp.MachineId == Setting.Values.MachineId)
{
tcp = null;
Setting.Values.MachineId = Common.Ran.Next();
Setting.Values.MachineId = Encryption.Ran.Next();
InitAndCleanup.UpdateMachineTimeAndID();
InitAndCleanup.PleaseReopenSocket = InitAndCleanup.REOPEN_WHEN_HOTKEY;

View File

@@ -70,7 +70,7 @@ namespace MouseWithoutBorders.Class
continue;
}
if (!Common.IsMyDesktopActive())
if (!WinAPI.IsMyDesktopActive())
{
// We can just throw the SocketException but to avoid a redundant log entry:
throw new ExpectedSocketException($"{nameof(StartServer)}: The desktop is no longer active.");

View File

@@ -270,15 +270,15 @@ internal static class Clipboard
int index = 0;
int len;
DATA package = new();
byte[] buf = new byte[Common.PACKAGE_SIZE_EX];
int dataStart = Common.PACKAGE_SIZE_EX - DATA_SIZE;
byte[] buf = new byte[Package.PACKAGE_SIZE_EX];
int dataStart = Package.PACKAGE_SIZE_EX - DATA_SIZE;
while (true)
{
if ((index + DATA_SIZE) > l)
{
len = l - index;
Array.Clear(buf, 0, Common.PACKAGE_SIZE_EX);
Array.Clear(buf, 0, Package.PACKAGE_SIZE_EX);
}
else
{
@@ -315,7 +315,7 @@ internal static class Clipboard
}
MemoryStream m = new();
int dataStart = Common.PACKAGE_SIZE_EX - DATA_SIZE;
int dataStart = Package.PACKAGE_SIZE_EX - DATA_SIZE;
m.Write(data.Bytes, dataStart, DATA_SIZE);
int unexpectedCount = 0;
@@ -809,27 +809,27 @@ internal static class Clipboard
MachineName = Common.MachineName,
};
byte[] buf = new byte[Common.PACKAGE_SIZE_EX];
byte[] buf = new byte[Package.PACKAGE_SIZE_EX];
NetworkStream ns = new(s);
enStream = Common.GetEncryptedStream(ns);
enStream = Encryption.GetEncryptedStream(ns);
Common.SendOrReceiveARandomDataBlockPerInitialIV(enStream);
Logger.LogDebug($"{nameof(ShakeHand)}: Writing header package.");
enStream.Write(package.Bytes, 0, Common.PACKAGE_SIZE_EX);
enStream.Write(package.Bytes, 0, Package.PACKAGE_SIZE_EX);
Logger.LogDebug($"{nameof(ShakeHand)}: Sent: clientPush={clientPushData}, postAction={postAction}.");
deStream = Common.GetDecryptedStream(ns);
deStream = Encryption.GetDecryptedStream(ns);
Common.SendOrReceiveARandomDataBlockPerInitialIV(deStream, false);
Logger.LogDebug($"{nameof(ShakeHand)}: Reading header package.");
int bytesReceived = deStream.ReadEx(buf, 0, Common.PACKAGE_SIZE_EX);
int bytesReceived = deStream.ReadEx(buf, 0, Package.PACKAGE_SIZE_EX);
package.Bytes = buf;
string name = "Unknown";
if (bytesReceived == Common.PACKAGE_SIZE_EX)
if (bytesReceived == Package.PACKAGE_SIZE_EX)
{
if (package.Type is PackageType.Clipboard or PackageType.ClipboardPush)
{

View File

@@ -0,0 +1,25 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
// <summary>
// Package format/conversion.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
namespace MouseWithoutBorders.Core;
internal enum ClipboardPostAction : uint
{
Other = 0,
Desktop = 1,
Mspaint = 2,
}

View File

@@ -0,0 +1,150 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
// In X64, we are WOW
[module: SuppressMessage("Microsoft.Portability", "CA1900:ValueTypeFieldsShouldBePortable", Scope = "type", Target = "MouseWithoutBorders.Core.DATA", Justification = "Dotnet port with style preservation")]
// <summary>
// Package format/conversion.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
namespace MouseWithoutBorders.Core;
// The beauty of "union" in C#
[StructLayout(LayoutKind.Explicit)]
internal sealed class DATA
{
[FieldOffset(0)]
internal PackageType Type; // 4 (first byte = package type, 1 = checksum, 2+3 = magic no.)
[FieldOffset(sizeof(PackageType))]
internal int Id; // 4
[FieldOffset(sizeof(PackageType) + sizeof(uint))]
internal ID Src; // 4
[FieldOffset(sizeof(PackageType) + (2 * sizeof(uint)))]
internal ID Des; // 4
[FieldOffset(sizeof(PackageType) + (3 * sizeof(uint)))]
internal long DateTime;
[FieldOffset(sizeof(PackageType) + (3 * sizeof(uint)) + sizeof(long))]
internal KEYBDDATA Kd;
[FieldOffset(sizeof(PackageType) + (3 * sizeof(uint)))]
internal MOUSEDATA Md;
[FieldOffset(sizeof(PackageType) + (3 * sizeof(uint)))]
internal ID Machine1;
[FieldOffset(sizeof(PackageType) + (4 * sizeof(uint)))]
internal ID Machine2;
[FieldOffset(sizeof(PackageType) + (5 * sizeof(uint)))]
internal ID Machine3;
[FieldOffset(sizeof(PackageType) + (6 * sizeof(uint)))]
internal ID Machine4;
[FieldOffset(sizeof(PackageType) + (3 * sizeof(uint)))]
internal ClipboardPostAction PostAction;
[FieldOffset(sizeof(PackageType) + (7 * sizeof(uint)))]
private long machineNameP1;
[FieldOffset(sizeof(PackageType) + (7 * sizeof(uint)) + sizeof(long))]
private long machineNameP2;
[FieldOffset(sizeof(PackageType) + (7 * sizeof(uint)) + (2 * sizeof(long)))]
private long machineNameP3;
[FieldOffset(sizeof(PackageType) + (7 * sizeof(uint)) + (3 * sizeof(long)))]
private long machineNameP4;
internal string MachineName
{
get
{
string name = Common.GetString(BitConverter.GetBytes(machineNameP1))
+ Common.GetString(BitConverter.GetBytes(machineNameP2))
+ Common.GetString(BitConverter.GetBytes(machineNameP3))
+ Common.GetString(BitConverter.GetBytes(machineNameP4));
return name.Trim();
}
set
{
byte[] machineName = Common.GetBytes(value.PadRight(32, ' '));
machineNameP1 = BitConverter.ToInt64(machineName, 0);
machineNameP2 = BitConverter.ToInt64(machineName, 8);
machineNameP3 = BitConverter.ToInt64(machineName, 16);
machineNameP4 = BitConverter.ToInt64(machineName, 24);
}
}
public DATA()
{
}
public DATA(byte[] initialData)
{
Bytes = initialData;
}
internal byte[] Bytes
{
get
{
byte[] buf = new byte[IsBigPackage ? Package.PACKAGE_SIZE_EX : Package.PACKAGE_SIZE];
Array.Copy(StructToBytes(this), buf, IsBigPackage ? Package.PACKAGE_SIZE_EX : Package.PACKAGE_SIZE);
return buf;
}
set
{
Debug.Assert(value.Length <= Package.PACKAGE_SIZE_EX, "Length > package size");
byte[] buf = new byte[Package.PACKAGE_SIZE_EX];
Array.Copy(value, buf, value.Length);
BytesToStruct(buf, this);
}
}
internal bool IsBigPackage
{
get => Type == 0
? throw new InvalidOperationException("Package type not set.")
: Type switch
{
PackageType.Hello or PackageType.Awake or PackageType.Heartbeat or PackageType.Heartbeat_ex or PackageType.Handshake or PackageType.HandshakeAck or PackageType.ClipboardPush or PackageType.Clipboard or PackageType.ClipboardAsk or PackageType.ClipboardImage or PackageType.ClipboardText or PackageType.ClipboardDataEnd => true,
_ => (Type & PackageType.Matrix) == PackageType.Matrix,
};
}
private byte[] StructToBytes(object structObject)
{
byte[] bytes = new byte[Package.PACKAGE_SIZE_EX];
GCHandle bHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
Marshal.StructureToPtr(structObject, Marshal.UnsafeAddrOfPinnedArrayElement(bytes, 0), false);
bHandle.Free();
return bytes;
}
private void BytesToStruct(byte[] value, object structObject)
{
GCHandle bHandle = GCHandle.Alloc(value, GCHandleType.Pinned);
Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(value, 0), structObject);
bHandle.Free();
}
}

View File

@@ -67,20 +67,20 @@ internal static class DragDrop
return;
}
if (wParam == Common.WM_LBUTTONDOWN)
if (wParam == WM.WM_LBUTTONDOWN)
{
MouseDown = true;
DragMachine = MachineStuff.desMachineID;
MachineStuff.dropMachineID = ID.NONE;
Logger.LogDebug("DragDropStep01: MouseDown");
}
else if (wParam == Common.WM_LBUTTONUP)
else if (wParam == WM.WM_LBUTTONUP)
{
MouseDown = false;
Logger.LogDebug("DragDropStep01: MouseUp");
}
if (wParam == Common.WM_RBUTTONUP && IsDropping)
if (wParam == WM.WM_RBUTTONUP && IsDropping)
{
IsDropping = false;
Clipboard.LastIDWithClipboardData = ID.NONE;
@@ -252,7 +252,7 @@ internal static class DragDrop
internal static void DragDropStep09(int wParam)
{
if (wParam == Common.WM_MOUSEMOVE && IsDropping)
if (wParam == WM.WM_MOUSEMOVE && IsDropping)
{
// Show/Move form
Common.DoSomethingInUIThread(() =>
@@ -260,7 +260,7 @@ internal static class DragDrop
_ = NativeMethods.PostMessage(Common.MainForm.Handle, NativeMethods.WM_SHOW_DRAG_DROP, (IntPtr)0, (IntPtr)0);
});
}
else if (wParam == Common.WM_LBUTTONUP && (IsDropping || IsDragging))
else if (wParam == WM.WM_LBUTTONUP && (IsDropping || IsDragging))
{
if (IsDropping)
{

View File

@@ -0,0 +1,245 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Concurrent;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Threading.Tasks;
// <summary>
// Encrypt/decrypt implementation.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
namespace MouseWithoutBorders.Core;
internal static class Encryption
{
#pragma warning disable SYSLIB0021
private static AesCryptoServiceProvider symAl;
#pragma warning restore SYSLIB0021
#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter
internal static string myKey;
#pragma warning restore SA1307
private static uint magicNumber;
private static Random ran = new(); // Used for non encryption related functionality.
internal const int SymAlBlockSize = 16;
/// <summary>
/// This is used for the first encryption block, the following blocks will be combined with the cipher text of the previous block.
/// Thus identical blocks in the socket stream would be encrypted to different cipher text blocks.
/// The first block is a handshake one containing random data.
/// Related Unit Test: TestEncryptDecrypt
/// </summary>
private static readonly string InitialIV = ulong.MaxValue.ToString(CultureInfo.InvariantCulture);
internal static Random Ran
{
get => Encryption.ran ??= new Random();
set => Encryption.ran = value;
}
internal static uint MagicNumber
{
get => Encryption.magicNumber;
set => Encryption.magicNumber = value;
}
internal static string MyKey
{
get => Encryption.myKey;
set
{
if (Encryption.myKey != value)
{
Encryption.myKey = value;
_ = Task.Factory.StartNew(
() => Encryption.GenLegalKey(),
System.Threading.CancellationToken.None,
TaskCreationOptions.None,
TaskScheduler.Default); // Cache the key to improve UX.
}
}
}
private static string KeyDisplayedText(string key)
{
string displayedValue = string.Empty;
int i = 0;
do
{
int length = Math.Min(4, key.Length - i);
displayedValue += string.Concat(key.AsSpan(i, length), " ");
i += 4;
}
while (i < key.Length - 1);
return displayedValue.Trim();
}
internal static bool GeneratedKey { get; set; }
internal static bool KeyCorrupted { get; set; }
internal static void InitEncryption()
{
try
{
if (symAl == null)
{
#pragma warning disable SYSLIB0021 // No proper replacement for now
symAl = new AesCryptoServiceProvider();
#pragma warning restore SYSLIB0021
symAl.KeySize = 256;
symAl.BlockSize = SymAlBlockSize * 8;
symAl.Padding = PaddingMode.Zeros;
symAl.Mode = CipherMode.CBC;
symAl.GenerateIV();
}
}
catch (Exception e)
{
Logger.Log(e);
}
}
private static readonly ConcurrentDictionary<string, byte[]> LegalKeyDictionary = new(StringComparer.OrdinalIgnoreCase);
private static byte[] GenLegalKey()
{
byte[] rv;
string myKey = Encryption.MyKey;
if (!LegalKeyDictionary.TryGetValue(myKey, out byte[] value))
{
Rfc2898DeriveBytes key = new(
myKey,
Common.GetBytesU(InitialIV),
50000,
HashAlgorithmName.SHA512);
rv = key.GetBytes(32);
_ = LegalKeyDictionary.AddOrUpdate(myKey, rv, (k, v) => rv);
}
else
{
rv = value;
}
return rv;
}
private static byte[] GenLegalIV()
{
string st = InitialIV;
int ivLength = symAl.IV.Length;
if (st.Length > ivLength)
{
st = st[..ivLength];
}
else if (st.Length < ivLength)
{
st = st.PadRight(ivLength, ' ');
}
return Common.GetBytes(st);
}
internal static Stream GetEncryptedStream(Stream encryptedStream)
{
ICryptoTransform encryptor;
encryptor = symAl.CreateEncryptor(GenLegalKey(), GenLegalIV());
return new CryptoStream(encryptedStream, encryptor, CryptoStreamMode.Write);
}
internal static Stream GetDecryptedStream(Stream encryptedStream)
{
ICryptoTransform decryptor;
decryptor = symAl.CreateDecryptor(GenLegalKey(), GenLegalIV());
return new CryptoStream(encryptedStream, decryptor, CryptoStreamMode.Read);
}
internal static uint Get24BitHash(string st)
{
if (string.IsNullOrEmpty(st))
{
return 0;
}
byte[] bytes = new byte[Package.PACKAGE_SIZE];
for (int i = 0; i < Package.PACKAGE_SIZE; i++)
{
if (i < st.Length)
{
bytes[i] = (byte)st[i];
}
}
var hash = SHA512.Create();
byte[] hashValue = hash.ComputeHash(bytes);
for (int i = 0; i < 50000; i++)
{
hashValue = hash.ComputeHash(hashValue);
}
Logger.LogDebug(string.Format(CultureInfo.CurrentCulture, "magic: {0},{1},{2}", hashValue[0], hashValue[1], hashValue[^1]));
hash.Clear();
return (uint)((hashValue[0] << 23) + (hashValue[1] << 16) + (hashValue[^1] << 8) + hashValue[2]);
}
internal static string GetDebugInfo(string st)
{
return string.IsNullOrEmpty(st) ? st : ((byte)(Common.GetBytesU(st).Sum(value => value) % 256)).ToString(CultureInfo.InvariantCulture);
}
internal static string CreateDefaultKey()
{
return CreateRandomKey();
}
private const int PW_LENGTH = 16;
internal static string CreateRandomKey()
{
// Not including characters like "'`O0& since they are confusing to users.
string[] chars = new[] { "abcdefghjkmnpqrstuvxyz", "ABCDEFGHJKMNPQRSTUVXYZ", "123456789", "~!@#$%^*()_-+=:;<,>.?/\\|[]" };
char[][] charactersUsedForKey = chars.Select(charset => Enumerable.Range(0, charset.Length - 1).Select(i => charset[i]).ToArray()).ToArray();
byte[] randomData = new byte[1];
string key = string.Empty;
do
{
foreach (string set in chars)
{
randomData = RandomNumberGenerator.GetBytes(1);
key += set[randomData[0] % set.Length];
if (key.Length >= PW_LENGTH)
{
break;
}
}
}
while (key.Length < PW_LENGTH);
return key;
}
internal static bool IsKeyValid(string key, out string error)
{
error = string.IsNullOrEmpty(key) || key.Length < 16
? "Key must have at least 16 characters in length (spaces are discarded). Key must be auto generated in one of the machines."
: null;
return error == null;
}
}

View File

@@ -70,7 +70,7 @@ internal static class Event
// Check if easy mouse setting is enabled.
bool isEasyMouseEnabled = IsSwitchingByMouseEnabled();
if (isEasyMouseEnabled && Common.Sk != null && (Common.DesMachineID == Common.MachineID || !Setting.Values.MoveMouseRelatively) && e.dwFlags == Common.WM_MOUSEMOVE)
if (isEasyMouseEnabled && Common.Sk != null && (Common.DesMachineID == Common.MachineID || !Setting.Values.MoveMouseRelatively) && e.dwFlags == WM.WM_MOUSEMOVE)
{
Point p = MachineStuff.MoveToMyNeighbourIfNeeded(e.X, e.Y, MachineStuff.desMachineID);
@@ -115,7 +115,7 @@ internal static class Event
Common.SkSend(MousePackage, null, false);
if (MousePackage.Md.dwFlags is Common.WM_LBUTTONUP or Common.WM_RBUTTONUP)
if (MousePackage.Md.dwFlags is WM.WM_LBUTTONUP or WM.WM_RBUTTONUP)
{
Thread.Sleep(10);
}
@@ -265,7 +265,7 @@ internal static class Event
KeybdPackage.Kd = e;
KeybdPackage.DateTime = Common.GetTick();
Common.SkSend(KeybdPackage, null, false);
if (KeybdPackage.Kd.dwFlags is Common.WM_KEYUP or Common.WM_SYSKEYUP)
if (KeybdPackage.Kd.dwFlags is WM.WM_KEYUP or WM.WM_SYSKEYUP)
{
Thread.Sleep(10);
}

View File

@@ -290,7 +290,7 @@ internal static class Helper
return;
}
if (!Common.IsMyDesktopActive())
if (!WinAPI.IsMyDesktopActive())
{
return;
}
@@ -314,7 +314,7 @@ internal static class Helper
_ = Launch.CreateProcessInInputDesktopSession(
$"\"{Path.GetDirectoryName(Application.ExecutablePath)}\\{HelperProcessName}.exe\"",
string.Empty,
Common.GetInputDesktop(),
WinAPI.GetInputDesktop(),
0);
Clipboard.HasSwitchedMachineSinceLastCopy = true;
@@ -379,7 +379,7 @@ internal static class Helper
log += "=============================================================================================================================\r\n";
log += $"{Application.ProductName} version {Application.ProductVersion}\r\n";
log += $"{Setting.Values.Username}/{Common.GetDebugInfo(Common.MyKey)}\r\n";
log += $"{Setting.Values.Username}/{Encryption.GetDebugInfo(Encryption.MyKey)}\r\n";
log += $"{Common.MachineName}/{Common.MachineID}/{Common.DesMachineID}\r\n";
log += $"Id: {Setting.Values.DeviceId}\r\n";
log += $"Matrix: {string.Join(",", MachineStuff.MachineMatrix)}\r\n";

View File

@@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// <summary>
// Package format/conversion.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
namespace MouseWithoutBorders.Core;
internal enum ID : uint
{
NONE = 0,
ALL = 255,
}

View File

@@ -89,23 +89,23 @@ internal static class InitAndCleanup
internal static void Init()
{
_ = Helper.GetUserName();
Common.GeneratedKey = true;
Encryption.GeneratedKey = true;
try
{
Common.MyKey = Setting.Values.MyKey;
Encryption.MyKey = Setting.Values.MyKey;
int tmp = Setting.Values.MyKeyDaysToExpire;
}
catch (FormatException e)
{
Common.KeyCorrupted = true;
Setting.Values.MyKey = Common.MyKey = Common.CreateRandomKey();
Encryption.KeyCorrupted = true;
Setting.Values.MyKey = Encryption.MyKey = Encryption.CreateRandomKey();
Logger.Log(e.Message);
}
catch (CryptographicException e)
{
Common.KeyCorrupted = true;
Setting.Values.MyKey = Common.MyKey = Common.CreateRandomKey();
Encryption.KeyCorrupted = true;
Setting.Values.MyKey = Encryption.MyKey = Encryption.CreateRandomKey();
Logger.Log(e.Message);
}
@@ -127,14 +127,14 @@ internal static class InitAndCleanup
bool dummy = Setting.Values.DrawMouseEx;
Common.Is64bitOS = IntPtr.Size == 8;
Common.tcpPort = Setting.Values.TcpPort;
Common.GetScreenConfig();
Common.PackageSent = new PackageMonitor(0);
Common.PackageReceived = new PackageMonitor(0);
WinAPI.GetScreenConfig();
Package.PackageSent = new PackageMonitor(0);
Package.PackageReceived = new PackageMonitor(0);
SetupMachineNameAndID();
Common.InitEncryption();
Encryption.InitEncryption();
CreateHelperThreads();
SystemEvents.DisplaySettingsChanged += new EventHandler(Common.SystemEvents_DisplaySettingsChanged);
SystemEvents.DisplaySettingsChanged += new EventHandler(WinAPI.SystemEvents_DisplaySettingsChanged);
NetworkChange.NetworkAvailabilityChanged += new NetworkAvailabilityChangedEventHandler(NetworkChange_NetworkAvailabilityChanged);
SystemEvents.PowerModeChanged += new PowerModeChangedEventHandler(SystemEvents_PowerModeChanged);
PleaseReopenSocket = 9;
@@ -220,7 +220,7 @@ internal static class InitAndCleanup
lastReleaseAllKeysCall = Common.GetTick();
KEYBDDATA kd;
kd.dwFlags = (int)Common.LLKHF.UP;
kd.dwFlags = (int)WM.LLKHF.UP;
VK[] keys = new VK[]
{
@@ -266,7 +266,7 @@ internal static class InitAndCleanup
true);
}
if (!Common.IsMyDesktopActive())
if (!WinAPI.IsMyDesktopActive())
{
PleaseReopenSocket = 0;
}

View File

@@ -0,0 +1,25 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
// <summary>
// Package format/conversion.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
namespace MouseWithoutBorders.Core;
[StructLayout(LayoutKind.Sequential)]
internal struct KEYBDDATA
{
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Same name as in winAPI")]
internal int wVk;
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Same name as in winAPI")]
internal int dwFlags;
}

View File

@@ -121,52 +121,52 @@ internal static class Logger
{
string log;
if (!lastPackageSent.Equals(Common.PackageSent))
if (!lastPackageSent.Equals(Package.PackageSent))
{
log = string.Format(
CultureInfo.CurrentCulture,
"SENT:" + HeaderSENT,
Common.PackageSent.Heartbeat,
Common.PackageSent.Keyboard,
Common.PackageSent.Mouse,
Common.PackageSent.Hello,
Common.PackageSent.Matrix,
Common.PackageSent.ClipboardText,
Common.PackageSent.ClipboardImage,
Common.PackageSent.ByeBye,
Common.PackageSent.Clipboard,
Common.PackageSent.ClipboardDragDrop,
Common.PackageSent.ClipboardDragDropEnd,
Common.PackageSent.ExplorerDragDrop,
Package.PackageSent.Heartbeat,
Package.PackageSent.Keyboard,
Package.PackageSent.Mouse,
Package.PackageSent.Hello,
Package.PackageSent.Matrix,
Package.PackageSent.ClipboardText,
Package.PackageSent.ClipboardImage,
Package.PackageSent.ByeBye,
Package.PackageSent.Clipboard,
Package.PackageSent.ClipboardDragDrop,
Package.PackageSent.ClipboardDragDropEnd,
Package.PackageSent.ExplorerDragDrop,
Event.inputEventCount,
Common.PackageSent.Nil);
Package.PackageSent.Nil);
Log(log);
lastPackageSent = Common.PackageSent; // Copy data
lastPackageSent = Package.PackageSent; // Copy data
}
if (!lastPackageReceived.Equals(Common.PackageReceived))
if (!lastPackageReceived.Equals(Package.PackageReceived))
{
log = string.Format(
CultureInfo.CurrentCulture,
"RECEIVED:" + HeaderRECEIVED,
Common.PackageReceived.Heartbeat,
Common.PackageReceived.Keyboard,
Common.PackageReceived.Mouse,
Common.PackageReceived.Hello,
Common.PackageReceived.Matrix,
Common.PackageReceived.ClipboardText,
Common.PackageReceived.ClipboardImage,
Common.PackageReceived.ByeBye,
Common.PackageReceived.Clipboard,
Common.PackageReceived.ClipboardDragDrop,
Common.PackageReceived.ClipboardDragDropEnd,
Common.PackageReceived.ExplorerDragDrop,
Package.PackageReceived.Heartbeat,
Package.PackageReceived.Keyboard,
Package.PackageReceived.Mouse,
Package.PackageReceived.Hello,
Package.PackageReceived.Matrix,
Package.PackageReceived.ClipboardText,
Package.PackageReceived.ClipboardImage,
Package.PackageReceived.ByeBye,
Package.PackageReceived.Clipboard,
Package.PackageReceived.ClipboardDragDrop,
Package.PackageReceived.ClipboardDragDropEnd,
Package.PackageReceived.ExplorerDragDrop,
Event.invalidPackageCount,
Common.PackageReceived.Nil,
Package.PackageReceived.Nil,
Receiver.processedPackageCount,
Receiver.skippedPackageCount);
Log(log);
lastPackageReceived = Common.PackageReceived;
lastPackageReceived = Package.PackageReceived;
}
}
@@ -209,9 +209,9 @@ internal static class Logger
"Private Mem: " + (Process.GetCurrentProcess().PrivateMemorySize64 / 1024).ToString(CultureInfo.CurrentCulture) + "KB",
sb.ToString());
if (!string.IsNullOrEmpty(Common.myKey))
if (!string.IsNullOrEmpty(Encryption.myKey))
{
log = log.Replace(Common.MyKey, Common.GetDebugInfo(Common.MyKey));
log = log.Replace(Encryption.MyKey, Encryption.GetDebugInfo(Encryption.MyKey));
}
log += Thread.DumpThreadsStack();
@@ -251,14 +251,18 @@ internal static class Logger
{
typeof(Clipboard),
typeof(DragDrop),
typeof(Encryption),
typeof(Event),
typeof(InitAndCleanup),
typeof(Helper),
typeof(Launch),
typeof(Logger),
typeof(MachineStuff),
typeof(Package),
typeof(Receiver),
typeof(Service),
typeof(WinAPI),
typeof(WM),
};
foreach (var staticType in staticTypes)
{
@@ -294,7 +298,7 @@ internal static class Logger
// strArr[3] = t.FullName;
strArr[4] = " = ";
strArr[5] = objName.Equals("myKey", StringComparison.OrdinalIgnoreCase)
? Common.GetDebugInfo(objString)
? Encryption.GetDebugInfo(objString)
: objName.Equals("lastClipboardObject", StringComparison.OrdinalIgnoreCase)
? string.Empty
: objString

View File

@@ -0,0 +1,26 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
// <summary>
// Package format/conversion.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
namespace MouseWithoutBorders.Core;
[StructLayout(LayoutKind.Sequential)]
internal struct MOUSEDATA
{
internal int X;
internal int Y;
internal int WheelDelta;
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Same name as in winAPI")]
internal int dwFlags;
}

View File

@@ -221,9 +221,9 @@ internal static class MachineStuff
if (Setting.Values.BlockMouseAtCorners)
{
lock (Common.SensitivePoints)
lock (WinAPI.SensitivePoints)
{
foreach (Point p in Common.SensitivePoints)
foreach (Point p in WinAPI.SensitivePoints)
{
if (Math.Abs(p.X - x) < 100 && Math.Abs(p.Y - y) < 100)
{
@@ -793,8 +793,8 @@ internal static class MachineStuff
internal static void ShowSetupForm(bool reopenSockets = false)
{
Logger.LogDebug("========== BEGIN THE SETUP EXPERIENCE ==========", true);
Setting.Values.MyKey = Common.MyKey = Common.CreateRandomKey();
Common.GeneratedKey = true;
Setting.Values.MyKey = Encryption.MyKey = Encryption.CreateRandomKey();
Encryption.GeneratedKey = true;
if (Process.GetCurrentProcess().SessionId != NativeMethods.WTSGetActiveConsoleSessionId())
{
@@ -1067,7 +1067,7 @@ internal static class MachineStuff
internal static void AssertOneInstancePerDesktopSession()
{
string eventName = $"Global\\{Application.ProductName}-{FrmAbout.AssemblyVersion}-{Common.GetMyDesktop()}-{Common.CurrentProcess.SessionId}";
string eventName = $"Global\\{Application.ProductName}-{FrmAbout.AssemblyVersion}-{WinAPI.GetMyDesktop()}-{Common.CurrentProcess.SessionId}";
oneInstanceCheck = new EventWaitHandle(false, EventResetMode.ManualReset, eventName, out bool created);
if (!created)

View File

@@ -0,0 +1,23 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// <summary>
// Package format/conversion.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
namespace MouseWithoutBorders.Core;
internal static class Package
{
internal const byte PACKAGE_SIZE = 32;
internal const byte PACKAGE_SIZE_EX = 64;
private const byte WP_PACKAGE_SIZE = 6;
internal static PackageMonitor PackageSent;
internal static PackageMonitor PackageReceived;
internal static int PackageID;
}

View File

@@ -0,0 +1,38 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// <summary>
// Package format/conversion.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
namespace MouseWithoutBorders.Core;
internal struct PackageMonitor
{
internal ulong Keyboard;
internal ulong Mouse;
internal ulong Heartbeat;
internal ulong ByeBye;
internal ulong Hello;
internal ulong Matrix;
internal ulong ClipboardText;
internal ulong ClipboardImage;
internal ulong Clipboard;
internal ulong ClipboardDragDrop;
internal ulong ClipboardDragDropEnd;
internal ulong ClipboardAsk;
internal ulong ExplorerDragDrop;
internal ulong Nil;
internal PackageMonitor(ulong value)
{
ClipboardDragDrop = ClipboardDragDropEnd = ExplorerDragDrop =
Keyboard = Mouse = Heartbeat = ByeBye = Hello = Clipboard =
Matrix = ClipboardImage = ClipboardText = Nil = ClipboardAsk = value;
}
}

View File

@@ -0,0 +1,57 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// <summary>
// Package format/conversion.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
namespace MouseWithoutBorders.Core;
internal enum PackageType // : int
{
// Search for PACKAGE_TYPE_RELATED before changing these!
Invalid = 0xFF,
Error = 0xFE,
Hi = 2,
Hello = 3,
ByeBye = 4,
Heartbeat = 20,
Awake = 21,
HideMouse = 50,
Heartbeat_ex = 51,
Heartbeat_ex_l2 = 52,
Heartbeat_ex_l3 = 53,
Clipboard = 69,
ClipboardDragDrop = 70,
ClipboardDragDropEnd = 71,
ExplorerDragDrop = 72,
ClipboardCapture = 73,
CaptureScreenCommand = 74,
ClipboardDragDropOperation = 75,
ClipboardDataEnd = 76,
MachineSwitched = 77,
ClipboardAsk = 78,
ClipboardPush = 79,
NextMachine = 121,
Keyboard = 122,
Mouse = 123,
ClipboardText = 124,
ClipboardImage = 125,
Handshake = 126,
HandshakeAck = 127,
Matrix = 128,
MatrixSwapFlag = 2,
MatrixTwoRowFlag = 4,
}

View File

@@ -93,7 +93,7 @@ internal static class Receiver
switch (package.Type)
{
case PackageType.Keyboard:
Common.PackageReceived.Keyboard++;
Package.PackageReceived.Keyboard++;
if (package.Des == Common.MachineID || package.Des == ID.ALL)
{
JustGotAKey = Common.GetTick();
@@ -102,7 +102,7 @@ internal static class Receiver
bool nonElevated = Common.RunWithNoAdminRight && false;
if (nonElevated && Setting.Values.OneWayControlMode)
{
if ((package.Kd.dwFlags & (int)Common.LLKHF.UP) == (int)Common.LLKHF.UP)
if ((package.Kd.dwFlags & (int)WM.LLKHF.UP) == (int)WM.LLKHF.UP)
{
Helper.ShowOneWayModeMessage();
}
@@ -116,7 +116,7 @@ internal static class Receiver
break;
case PackageType.Mouse:
Common.PackageReceived.Mouse++;
Package.PackageReceived.Mouse++;
if (package.Des == Common.MachineID || package.Des == ID.ALL)
{
@@ -127,16 +127,16 @@ internal static class Receiver
// NOTE(@yuyoyuppe): disabled to drop elevation requirement
bool nonElevated = Common.RunWithNoAdminRight && false;
if (nonElevated && Setting.Values.OneWayControlMode && package.Md.dwFlags != Common.WM_MOUSEMOVE)
if (nonElevated && Setting.Values.OneWayControlMode && package.Md.dwFlags != WM.WM_MOUSEMOVE)
{
if (!DragDrop.IsDropping)
{
if (package.Md.dwFlags is Common.WM_LBUTTONDOWN or Common.WM_RBUTTONDOWN)
if (package.Md.dwFlags is WM.WM_LBUTTONDOWN or WM.WM_RBUTTONDOWN)
{
Helper.ShowOneWayModeMessage();
}
}
else if (package.Md.dwFlags is Common.WM_LBUTTONUP or Common.WM_RBUTTONUP)
else if (package.Md.dwFlags is WM.WM_LBUTTONUP or WM.WM_RBUTTONUP)
{
DragDrop.IsDropping = false;
}
@@ -146,7 +146,7 @@ internal static class Receiver
if (Math.Abs(package.Md.X) >= Event.MOVE_MOUSE_RELATIVE && Math.Abs(package.Md.Y) >= Event.MOVE_MOUSE_RELATIVE)
{
if (package.Md.dwFlags == Common.WM_MOUSEMOVE)
if (package.Md.dwFlags == WM.WM_MOUSEMOVE)
{
InputSimulation.MoveMouseRelative(
package.Md.X < 0 ? package.Md.X + Event.MOVE_MOUSE_RELATIVE : package.Md.X - Event.MOVE_MOUSE_RELATIVE,
@@ -203,19 +203,19 @@ internal static class Receiver
break;
case PackageType.ExplorerDragDrop:
Common.PackageReceived.ExplorerDragDrop++;
Package.PackageReceived.ExplorerDragDrop++;
DragDrop.DragDropStep03(package);
break;
case PackageType.Heartbeat:
case PackageType.Heartbeat_ex:
Common.PackageReceived.Heartbeat++;
Package.PackageReceived.Heartbeat++;
Common.GeneratedKey = Common.GeneratedKey || package.Type == PackageType.Heartbeat_ex;
Encryption.GeneratedKey = Encryption.GeneratedKey || package.Type == PackageType.Heartbeat_ex;
if (Common.GeneratedKey)
if (Encryption.GeneratedKey)
{
Setting.Values.MyKey = Common.MyKey;
Setting.Values.MyKey = Encryption.MyKey;
Common.SendPackage(ID.ALL, PackageType.Heartbeat_ex_l2);
}
@@ -230,26 +230,26 @@ internal static class Receiver
break;
case PackageType.Heartbeat_ex_l2:
Common.GeneratedKey = true;
Setting.Values.MyKey = Common.MyKey;
Encryption.GeneratedKey = true;
Setting.Values.MyKey = Encryption.MyKey;
Common.SendPackage(ID.ALL, PackageType.Heartbeat_ex_l3);
break;
case PackageType.Heartbeat_ex_l3:
Common.GeneratedKey = true;
Setting.Values.MyKey = Common.MyKey;
Encryption.GeneratedKey = true;
Setting.Values.MyKey = Encryption.MyKey;
break;
case PackageType.Awake:
Common.PackageReceived.Heartbeat++;
Package.PackageReceived.Heartbeat++;
_ = MachineStuff.AddToMachinePool(package);
Common.HumanBeingDetected();
break;
case PackageType.Hello:
Common.PackageReceived.Hello++;
Package.PackageReceived.Hello++;
Common.SendHeartBeat();
string newMachine = MachineStuff.AddToMachinePool(package);
if (Setting.Values.MachineMatrixString == null)
@@ -262,16 +262,16 @@ internal static class Receiver
break;
case PackageType.Hi:
Common.PackageReceived.Hello++;
Package.PackageReceived.Hello++;
break;
case PackageType.ByeBye:
Common.PackageReceived.ByeBye++;
Package.PackageReceived.ByeBye++;
Common.ProcessByeByeMessage(package);
break;
case PackageType.Clipboard:
Common.PackageReceived.Clipboard++;
Package.PackageReceived.Clipboard++;
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
{
Clipboard.clipboardCopiedTime = Common.GetTick();
@@ -291,7 +291,7 @@ internal static class Receiver
break;
case PackageType.ClipboardCapture:
Common.PackageReceived.Clipboard++;
Package.PackageReceived.Clipboard++;
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
{
if (package.Des == Common.MachineID || package.Des == ID.ALL)
@@ -304,7 +304,7 @@ internal static class Receiver
break;
case PackageType.CaptureScreenCommand:
Common.PackageReceived.Clipboard++;
Package.PackageReceived.Clipboard++;
if (package.Des == Common.MachineID || package.Des == ID.ALL)
{
Common.SendImage(package.Src, Common.CaptureScreen());
@@ -313,7 +313,7 @@ internal static class Receiver
break;
case PackageType.ClipboardAsk:
Common.PackageReceived.ClipboardAsk++;
Package.PackageReceived.ClipboardAsk++;
if (package.Des == Common.MachineID)
{
@@ -344,17 +344,17 @@ internal static class Receiver
break;
case PackageType.ClipboardDragDrop:
Common.PackageReceived.ClipboardDragDrop++;
Package.PackageReceived.ClipboardDragDrop++;
DragDrop.DragDropStep08(package);
break;
case PackageType.ClipboardDragDropOperation:
Common.PackageReceived.ClipboardDragDrop++;
Package.PackageReceived.ClipboardDragDrop++;
DragDrop.DragDropStep08_2(package);
break;
case PackageType.ClipboardDragDropEnd:
Common.PackageReceived.ClipboardDragDropEnd++;
Package.PackageReceived.ClipboardDragDropEnd++;
DragDrop.DragDropStep12();
break;
@@ -363,11 +363,11 @@ internal static class Receiver
Clipboard.clipboardCopiedTime = 0;
if (package.Type == PackageType.ClipboardImage)
{
Common.PackageReceived.ClipboardImage++;
Package.PackageReceived.ClipboardImage++;
}
else
{
Common.PackageReceived.ClipboardText++;
Package.PackageReceived.ClipboardText++;
}
if (tcp != null)
@@ -390,7 +390,7 @@ internal static class Receiver
default:
if ((package.Type & PackageType.Matrix) == PackageType.Matrix)
{
Common.PackageReceived.Matrix++;
Package.PackageReceived.Matrix++;
MachineStuff.UpdateMachineMatrix(package);
break;
}

View File

@@ -0,0 +1,29 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using ManagedCommon;
using Microsoft.PowerToys.Telemetry;
namespace MouseWithoutBorders.Core;
internal static class ShutdownWithPowerToys
{
internal static void WaitForPowerToysRunner(ETWTrace etwTrace)
{
try
{
RunnerHelper.WaitForPowerToysRunnerExitFallback(() =>
{
etwTrace?.Dispose();
Common.MainForm.Quit(true, false);
});
}
catch (Exception e)
{
Logger.Log(e);
}
}
}

View File

@@ -0,0 +1,88 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// <summary>
// Virtual key constants.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
namespace MouseWithoutBorders.Core;
internal enum VK : ushort
{
CAPITAL = 0x14,
NUMLOCK = 0x90,
SHIFT = 0x10,
CONTROL = 0x11,
MENU = 0x12,
ESCAPE = 0x1B,
BACK = 0x08,
TAB = 0x09,
RETURN = 0x0D,
PRIOR = 0x21,
NEXT = 0x22,
END = 0x23,
HOME = 0x24,
LEFT = 0x25,
UP = 0x26,
RIGHT = 0x27,
DOWN = 0x28,
SELECT = 0x29,
PRINT = 0x2A,
EXECUTE = 0x2B,
SNAPSHOT = 0x2C,
INSERT = 0x2D,
DELETE = 0x2E,
HELP = 0x2F,
NUMPAD0 = 0x60,
NUMPAD1 = 0x61,
NUMPAD2 = 0x62,
NUMPAD3 = 0x63,
NUMPAD4 = 0x64,
NUMPAD5 = 0x65,
NUMPAD6 = 0x66,
NUMPAD7 = 0x67,
NUMPAD8 = 0x68,
NUMPAD9 = 0x69,
MULTIPLY = 0x6A,
ADD = 0x6B,
SEPARATOR = 0x6C,
SUBTRACT = 0x6D,
DECIMAL = 0x6E,
DIVIDE = 0x6F,
F1 = 0x70,
F2 = 0x71,
F3 = 0x72,
F4 = 0x73,
F5 = 0x74,
F6 = 0x75,
F7 = 0x76,
F8 = 0x77,
F9 = 0x78,
F10 = 0x79,
F11 = 0x7A,
F12 = 0x7B,
OEM_1 = 0xBA,
OEM_PLUS = 0xBB,
OEM_COMMA = 0xBC,
OEM_MINUS = 0xBD,
OEM_PERIOD = 0xBE,
OEM_2 = 0xBF,
OEM_3 = 0xC0,
MEDIA_NEXT_TRACK = 0xB0,
MEDIA_PREV_TRACK = 0xB1,
MEDIA_STOP = 0xB2,
MEDIA_PLAY_PAUSE = 0xB3,
LWIN = 0x5B,
RWIN = 0x5C,
LSHIFT = 0xA0,
RSHIFT = 0xA1,
LCONTROL = 0xA2,
RCONTROL = 0xA3,
LMENU = 0xA4,
RMENU = 0xA5,
}

View File

@@ -0,0 +1,55 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
// <summary>
// Virtual key constants.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
namespace MouseWithoutBorders.Core;
internal partial class WM
{
internal const ushort KEYEVENTF_KEYDOWN = 0x0001;
internal const ushort KEYEVENTF_KEYUP = 0x0002;
internal const int WH_MOUSE = 7;
internal const int WH_KEYBOARD = 2;
internal const int WH_MOUSE_LL = 14;
internal const int WH_KEYBOARD_LL = 13;
internal const int WM_MOUSEMOVE = 0x200;
internal const int WM_LBUTTONDOWN = 0x201;
internal const int WM_RBUTTONDOWN = 0x204;
internal const int WM_MBUTTONDOWN = 0x207;
internal const int WM_XBUTTONDOWN = 0x20B;
internal const int WM_LBUTTONUP = 0x202;
internal const int WM_RBUTTONUP = 0x205;
internal const int WM_MBUTTONUP = 0x208;
internal const int WM_XBUTTONUP = 0x20C;
internal const int WM_LBUTTONDBLCLK = 0x203;
internal const int WM_RBUTTONDBLCLK = 0x206;
internal const int WM_MBUTTONDBLCLK = 0x209;
internal const int WM_MOUSEWHEEL = 0x020A;
internal const int WM_MOUSEHWHEEL = 0x020E;
internal const int WM_KEYDOWN = 0x100;
internal const int WM_KEYUP = 0x101;
internal const int WM_SYSKEYDOWN = 0x104;
internal const int WM_SYSKEYUP = 0x105;
[Flags]
internal enum LLKHF
{
EXTENDED = 0x01,
INJECTED = 0x10,
ALTDOWN = 0x20,
UP = 0x80,
}
}

View File

@@ -0,0 +1,359 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using MouseWithoutBorders.Class;
// <summary>
// Screen/Desktop helper functions.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
namespace MouseWithoutBorders.Core;
// Desktops, and GetScreenConfig routines
internal static class WinAPI
{
private static MyRectangle newDesktopBounds;
private static MyRectangle newPrimaryScreenBounds;
private static string activeDesktop;
private static string ActiveDesktop => WinAPI.activeDesktop;
internal static void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e)
{
GetScreenConfig();
}
internal static readonly List<Point> SensitivePoints = new();
private static bool MonitorEnumProc(IntPtr hMonitor, IntPtr hdcMonitor, ref NativeMethods.RECT lprcMonitor, IntPtr dwData)
{
// lprcMonitor is wrong!!! => using GetMonitorInfo(...)
// Log(String.Format( CultureInfo.CurrentCulture,"MONITOR: l{0}, t{1}, r{2}, b{3}", lprcMonitor.Left, lprcMonitor.Top, lprcMonitor.Right, lprcMonitor.Bottom));
NativeMethods.MonitorInfoEx mi = default;
mi.cbSize = Marshal.SizeOf(mi);
_ = NativeMethods.GetMonitorInfo(hMonitor, ref mi);
try
{
// For logging only
_ = NativeMethods.GetDpiForMonitor(hMonitor, 0, out uint dpiX, out uint dpiY);
Logger.Log(string.Format(CultureInfo.CurrentCulture, "MONITOR: ({0}, {1}, {2}, {3}). DPI: ({4}, {5})", mi.rcMonitor.Left, mi.rcMonitor.Top, mi.rcMonitor.Right, mi.rcMonitor.Bottom, dpiX, dpiY));
}
catch (DllNotFoundException)
{
Logger.Log("GetDpiForMonitor is unsupported in Windows 7 and lower.");
}
catch (EntryPointNotFoundException)
{
Logger.Log("GetDpiForMonitor is unsupported in Windows 7 and lower.");
}
catch (Exception e)
{
Logger.Log(e);
}
if (mi.rcMonitor.Left == 0 && mi.rcMonitor.Top == 0 && mi.rcMonitor.Right != 0 && mi.rcMonitor.Bottom != 0)
{
// Primary screen
_ = Interlocked.Exchange(ref Common.screenWidth, mi.rcMonitor.Right - mi.rcMonitor.Left);
_ = Interlocked.Exchange(ref Common.screenHeight, mi.rcMonitor.Bottom - mi.rcMonitor.Top);
newPrimaryScreenBounds.Left = mi.rcMonitor.Left;
newPrimaryScreenBounds.Top = mi.rcMonitor.Top;
newPrimaryScreenBounds.Right = mi.rcMonitor.Right;
newPrimaryScreenBounds.Bottom = mi.rcMonitor.Bottom;
}
else
{
if (mi.rcMonitor.Left < newDesktopBounds.Left)
{
newDesktopBounds.Left = mi.rcMonitor.Left;
}
if (mi.rcMonitor.Top < newDesktopBounds.Top)
{
newDesktopBounds.Top = mi.rcMonitor.Top;
}
if (mi.rcMonitor.Right > newDesktopBounds.Right)
{
newDesktopBounds.Right = mi.rcMonitor.Right;
}
if (mi.rcMonitor.Bottom > newDesktopBounds.Bottom)
{
newDesktopBounds.Bottom = mi.rcMonitor.Bottom;
}
}
lock (SensitivePoints)
{
SensitivePoints.Add(new Point(mi.rcMonitor.Left, mi.rcMonitor.Top));
SensitivePoints.Add(new Point(mi.rcMonitor.Right, mi.rcMonitor.Top));
SensitivePoints.Add(new Point(mi.rcMonitor.Right, mi.rcMonitor.Bottom));
SensitivePoints.Add(new Point(mi.rcMonitor.Left, mi.rcMonitor.Bottom));
}
return true;
}
internal static void GetScreenConfig()
{
try
{
Logger.LogDebug("==================== GetScreenConfig started");
newDesktopBounds = new MyRectangle();
newPrimaryScreenBounds = new MyRectangle();
newDesktopBounds.Left = newPrimaryScreenBounds.Left = Screen.PrimaryScreen.Bounds.Left;
newDesktopBounds.Top = newPrimaryScreenBounds.Top = Screen.PrimaryScreen.Bounds.Top;
newDesktopBounds.Right = newPrimaryScreenBounds.Right = Screen.PrimaryScreen.Bounds.Right;
newDesktopBounds.Bottom = newPrimaryScreenBounds.Bottom = Screen.PrimaryScreen.Bounds.Bottom;
Logger.Log(string.Format(
CultureInfo.CurrentCulture,
"logon = {0} PrimaryScreenBounds = {1},{2},{3},{4} desktopBounds = {5},{6},{7},{8}",
Common.RunOnLogonDesktop,
WinAPI.newPrimaryScreenBounds.Left,
WinAPI.newPrimaryScreenBounds.Top,
WinAPI.newPrimaryScreenBounds.Right,
WinAPI.newPrimaryScreenBounds.Bottom,
WinAPI.newDesktopBounds.Left,
WinAPI.newDesktopBounds.Top,
WinAPI.newDesktopBounds.Right,
WinAPI.newDesktopBounds.Bottom));
#if USE_MANAGED_ROUTINES
// Managed routines do not work well when running on secure desktop:(
screenWidth = Screen.PrimaryScreen.Bounds.Width;
screenHeight = Screen.PrimaryScreen.Bounds.Height;
screenCount = Screen.AllScreens.Length;
for (int i = 0; i < Screen.AllScreens.Length; i++)
{
if (Screen.AllScreens[i].Bounds.Left < desktopBounds.Left) desktopBounds.Left = Screen.AllScreens[i].Bounds.Left;
if (Screen.AllScreens[i].Bounds.Top < desktopBounds.Top) desktopBounds.Top = Screen.AllScreens[i].Bounds.Top;
if (Screen.AllScreens[i].Bounds.Right > desktopBounds.Right) desktopBounds.Right = Screen.AllScreens[i].Bounds.Right;
if (Screen.AllScreens[i].Bounds.Bottom > desktopBounds.Bottom) desktopBounds.Bottom = Screen.AllScreens[i].Bounds.Bottom;
}
#else
lock (SensitivePoints)
{
SensitivePoints.Clear();
}
NativeMethods.EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, MonitorEnumProc, IntPtr.Zero);
// 1000 calls to EnumDisplayMonitors cost a dozen of milliseconds
#endif
Interlocked.Exchange(ref MachineStuff.desktopBounds, newDesktopBounds);
Interlocked.Exchange(ref MachineStuff.primaryScreenBounds, newPrimaryScreenBounds);
Logger.Log(string.Format(
CultureInfo.CurrentCulture,
"logon = {0} PrimaryScreenBounds = {1},{2},{3},{4} desktopBounds = {5},{6},{7},{8}",
Common.RunOnLogonDesktop,
MachineStuff.PrimaryScreenBounds.Left,
MachineStuff.PrimaryScreenBounds.Top,
MachineStuff.PrimaryScreenBounds.Right,
MachineStuff.PrimaryScreenBounds.Bottom,
MachineStuff.DesktopBounds.Left,
MachineStuff.DesktopBounds.Top,
MachineStuff.DesktopBounds.Right,
MachineStuff.DesktopBounds.Bottom));
Logger.Log("==================== GetScreenConfig ended");
}
catch (Exception e)
{
Logger.Log(e);
}
}
#if USING_SCREEN_SAVER_ROUTINES
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int PostMessage(IntPtr hWnd, int wMsg, int wParam, int lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr OpenDesktop(string hDesktop, int Flags, bool Inherit, UInt32 DesiredAccess);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool CloseDesktop(IntPtr hDesktop);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool EnumDesktopWindows( IntPtr hDesktop, EnumDesktopWindowsProc callback, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool SystemParametersInfo(int uAction, int uParam, ref int pvParam, int flags);
private delegate bool EnumDesktopWindowsProc(IntPtr hDesktop, IntPtr lParam);
private const int WM_CLOSE = 16;
private const int SPI_GETSCREENSAVERRUNNING = 114;
internal static bool IsScreenSaverRunning()
{
int isRunning = 0;
SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0,ref isRunning, 0);
return (isRunning != 0);
}
internal static void CloseScreenSaver()
{
IntPtr hDesktop = OpenDesktop("Screen-saver", 0, false, DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS);
if (hDesktop != IntPtr.Zero)
{
LogDebug("Closing screen saver...");
EnumDesktopWindows(hDesktop, new EnumDesktopWindowsProc(CloseScreenSaverFunc), IntPtr.Zero);
CloseDesktop(hDesktop);
}
}
private static bool CloseScreenSaverFunc(IntPtr hWnd, IntPtr lParam)
{
if (IsWindowVisible(hWnd))
{
LogDebug("Posting WM_CLOSE to " + hWnd.ToString(CultureInfo.InvariantCulture));
PostMessage(hWnd, WM_CLOSE, 0, 0);
}
return true;
}
#endif
internal static string GetMyDesktop()
{
byte[] arThreadDesktop = new byte[256];
IntPtr hD = NativeMethods.GetThreadDesktop(NativeMethods.GetCurrentThreadId());
if (hD != IntPtr.Zero)
{
_ = NativeMethods.GetUserObjectInformation(hD, NativeMethods.UOI_NAME, arThreadDesktop, arThreadDesktop.Length, out _);
return Common.GetString(arThreadDesktop).Replace("\0", string.Empty);
}
return string.Empty;
}
internal static string GetInputDesktop()
{
byte[] arInputDesktop = new byte[256];
IntPtr hD = NativeMethods.OpenInputDesktop(0, false, NativeMethods.DESKTOP_READOBJECTS);
if (hD != IntPtr.Zero)
{
_ = NativeMethods.GetUserObjectInformation(hD, NativeMethods.UOI_NAME, arInputDesktop, arInputDesktop.Length, out _);
return Common.GetString(arInputDesktop).Replace("\0", string.Empty);
}
return string.Empty;
}
private static void StartMMService(string desktopToRunMouseWithoutBordersOn)
{
if (!Common.RunWithNoAdminRight)
{
Logger.LogDebug("*** Starting on active Desktop: " + desktopToRunMouseWithoutBordersOn);
Service.StartMouseWithoutBordersService(desktopToRunMouseWithoutBordersOn);
}
}
internal static void CheckForDesktopSwitchEvent(bool cleanupIfExit)
{
try
{
if (!IsMyDesktopActive() || Common.CurrentProcess.SessionId != NativeMethods.WTSGetActiveConsoleSessionId())
{
Helper.RunDDHelper(true);
int waitCount = 20;
while (NativeMethods.WTSGetActiveConsoleSessionId() == 0xFFFFFFFF && waitCount > 0)
{
waitCount--;
Logger.LogDebug("The session is detached/attached.");
Thread.Sleep(500);
}
string myDesktop = GetMyDesktop();
activeDesktop = GetInputDesktop();
Logger.LogDebug("*** Active Desktop = " + activeDesktop);
Logger.LogDebug("*** My Desktop = " + myDesktop);
if (myDesktop.Equals(activeDesktop, StringComparison.OrdinalIgnoreCase))
{
Logger.LogDebug("*** Active Desktop == My Desktop (TS session)");
}
if (!activeDesktop.Equals("winlogon", StringComparison.OrdinalIgnoreCase) &&
!activeDesktop.Equals("default", StringComparison.OrdinalIgnoreCase) &&
!activeDesktop.Equals("disconnect", StringComparison.OrdinalIgnoreCase))
{
try
{
StartMMService(activeDesktop);
}
catch (Exception e)
{
Logger.Log($"{nameof(CheckForDesktopSwitchEvent)}: {e}");
}
}
else
{
if (!myDesktop.Equals(activeDesktop, StringComparison.OrdinalIgnoreCase))
{
Logger.Log("*** Active Desktop <> My Desktop");
}
uint sid = NativeMethods.WTSGetActiveConsoleSessionId();
if (Process.GetProcessesByName(Common.BinaryName).Any(p => (uint)p.SessionId == sid))
{
Logger.Log("Found MouseWithoutBorders on the active session!");
}
else
{
Logger.Log("MouseWithoutBorders not found on the active session!");
StartMMService(null);
}
}
if (!myDesktop.Equals("winlogon", StringComparison.OrdinalIgnoreCase) &&
!myDesktop.Equals("default", StringComparison.OrdinalIgnoreCase))
{
Logger.LogDebug("*** Desktop inactive, exiting: " + myDesktop);
Setting.Values.LastX = Common.JUST_GOT_BACK_FROM_SCREEN_SAVER;
if (cleanupIfExit)
{
InitAndCleanup.Cleanup();
}
Process.GetCurrentProcess().KillProcess();
}
}
}
catch (Exception e)
{
Logger.Log(e);
}
}
private static Point p;
internal static bool IsMyDesktopActive()
{
return NativeMethods.GetCursorPos(ref p);
}
}

View File

@@ -42,7 +42,7 @@ namespace MouseWithoutBorders
protected string GetSecureKey()
{
return Common.MyKey;
return Encryption.MyKey;
}
private void BackButton_Click(object sender, EventArgs e)

View File

@@ -89,8 +89,8 @@ namespace MouseWithoutBorders
{
if (GetSecureKey() != SecurityCodeField.Text)
{
Common.MyKey = Regex.Replace(SecurityCodeField.Text, @"\s+", string.Empty);
SecurityCode = Common.MyKey;
Encryption.MyKey = Regex.Replace(SecurityCodeField.Text, @"\s+", string.Empty);
SecurityCode = Encryption.MyKey;
}
MachineStuff.MachineMatrix = new string[MachineStuff.MAX_MACHINE] { ComputerNameField.Text.Trim().ToUpper(CultureInfo.CurrentCulture), Common.MachineName.Trim(), string.Empty, string.Empty };

View File

@@ -135,7 +135,7 @@ namespace MouseWithoutBorders
internal void UpdateKeyTextBox()
{
_ = Helper.GetUserName();
textBoxEnc.Text = Common.MyKey;
textBoxEnc.Text = Encryption.MyKey;
}
private void InitAll()
@@ -505,19 +505,19 @@ namespace MouseWithoutBorders
private bool UpdateKey(string newKey)
{
if (!Common.IsKeyValid(newKey, out string rv))
if (!Encryption.IsKeyValid(newKey, out string rv))
{
ShowKeyErrorMsg(rv);
return false;
}
if (!newKey.Equals(Common.MyKey, StringComparison.OrdinalIgnoreCase))
if (!newKey.Equals(Encryption.MyKey, StringComparison.OrdinalIgnoreCase))
{
Common.MyKey = newKey;
Common.GeneratedKey = false;
Encryption.MyKey = newKey;
Encryption.GeneratedKey = false;
}
Common.MagicNumber = Common.Get24BitHash(Common.MyKey);
Encryption.MagicNumber = Encryption.Get24BitHash(Encryption.MyKey);
return true;
}
@@ -1116,10 +1116,10 @@ namespace MouseWithoutBorders
if (MessageBox.Show(message, Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
{
Setting.Values.MyKey = Common.MyKey = Common.CreateRandomKey();
textBoxEnc.Text = Common.MyKey;
Setting.Values.MyKey = Encryption.MyKey = Encryption.CreateRandomKey();
textBoxEnc.Text = Encryption.MyKey;
checkBoxShowKey.Checked = true;
Common.GeneratedKey = true;
Encryption.GeneratedKey = true;
ButtonOK_Click(null, null);
Common.ShowToolTip("New security key was generated, update other machines to the same key.", 10000, ToolTipIcon.Info, false);
}

View File

@@ -318,7 +318,7 @@ namespace MouseWithoutBorders
try
{
if (!Common.IsMyDesktopActive() || Common.CurrentProcess.SessionId != NativeMethods.WTSGetActiveConsoleSessionId())
if (!WinAPI.IsMyDesktopActive() || Common.CurrentProcess.SessionId != NativeMethods.WTSGetActiveConsoleSessionId())
{
myDesktopNotActive = true;
@@ -348,7 +348,7 @@ namespace MouseWithoutBorders
Common.Hook?.ResetLastSwitchKeys();
});
Common.CheckForDesktopSwitchEvent(true);
WinAPI.CheckForDesktopSwitchEvent(true);
}
}
else
@@ -369,21 +369,21 @@ namespace MouseWithoutBorders
if (myDesktopNotActive)
{
myDesktopNotActive = false;
Common.MyKey = Setting.Values.MyKey;
Encryption.MyKey = Setting.Values.MyKey;
}
MachineStuff.UpdateMachinePoolStringSetting();
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && (Setting.Values.FirstRun || Common.KeyCorrupted))
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && (Setting.Values.FirstRun || Encryption.KeyCorrupted))
{
if (!shownSetupFormOneTime)
{
shownSetupFormOneTime = true;
MachineStuff.ShowMachineMatrix();
if (Common.KeyCorrupted && !Setting.Values.FirstRun)
if (Encryption.KeyCorrupted && !Setting.Values.FirstRun)
{
Common.KeyCorrupted = false;
Encryption.KeyCorrupted = false;
string msg = "The security key is corrupted for some reason, please re-setup.";
MessageBox.Show(msg, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
@@ -490,9 +490,9 @@ namespace MouseWithoutBorders
if (count == 600)
{
if (!Common.GeneratedKey)
if (!Encryption.GeneratedKey)
{
Common.MyKey = Setting.Values.MyKey;
Encryption.MyKey = Setting.Values.MyKey;
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
{
@@ -505,7 +505,7 @@ namespace MouseWithoutBorders
Common.ShowToolTip("The security key must be auto generated in one of the machines.", 10000);
}
}
else if (!Common.KeyCorrupted && !Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && !Setting.Values.FirstRun && Common.AtLeastOneSocketConnected())
else if (!Encryption.KeyCorrupted && !Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && !Setting.Values.FirstRun && Common.AtLeastOneSocketConnected())
{
int myKeyDaysToExpire = Setting.Values.MyKeyDaysToExpire;
@@ -531,7 +531,7 @@ namespace MouseWithoutBorders
#if SHOW_ON_WINLOGON
// if (Common.RunOnLogonDesktop) ShowMouseWithoutBordersUiOnWinLogonDesktop(false);
#endif
Common.CheckForDesktopSwitchEvent(true);
WinAPI.CheckForDesktopSwitchEvent(true);
MachineStuff.UpdateClientSockets("helperTimer_Tick"); // Sockets may be closed by the remote host when both machines switch desktop at the same time.
}
@@ -582,7 +582,7 @@ namespace MouseWithoutBorders
int rv = 0;
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && Common.IsMyDesktopActive() && (rv = Helper.SendMessageToHelper(0x400, IntPtr.Zero, IntPtr.Zero)) <= 0)
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && WinAPI.IsMyDesktopActive() && (rv = Helper.SendMessageToHelper(0x400, IntPtr.Zero, IntPtr.Zero)) <= 0)
{
Logger.TelemetryLogTrace($"{Helper.HELPER_FORM_TEXT} not found: {rv}", SeverityLevel.Warning);
}

View File

@@ -46,79 +46,6 @@ avgSendTime = 0
maxSendTime = 0
totalSendCount = 0
totalSendTime = 0
magicNumber = 0
ran = System.Random
--_impl = System.Random+XoshiroImpl
----_s0 = ????????????
----_s1 = ????????????
----_s2 = ????????????
----_s3 = ????????????
--<Shared>k__BackingField = System.Random+ThreadSafeRandom
InitialIV = ????????????
<GeneratedKey>k__BackingField = False
<KeyCorrupted>k__BackingField = False
LegalKeyDictionary = Concurrent.ConcurrentDictionary`2[System.String,System.Byte[]]
--_tables = Concurrent.ConcurrentDictionary`2+Tables[System.String,System.Byte[]]
----_comparer = Generic.NonRandomizedStringEqualityComparer+OrdinalIgnoreCaseComparer
----_buckets = Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,System.Byte[]][]
------System.Collections.Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,System.Byte[]][] = Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,System.Byte[]][]: N/A
----_fastModBucketsMultiplier = 498560650640798693
----_locks = O[]
------System.Object[] = O[]: N/A
----_countPerLock = 32[]
------[0] = 0
------[1] = 0
------[2] = 0
------[3] = 0
------[4] = 0
------[5] = 0
------[6] = 0
------[7] = 0
--_budget = ????????????
--_growLockArray = True
--_comparerIsDefaultForClasses = False
PackageSent = MouseWithoutBorders.PackageMonitor
--Keyboard = 0
--Mouse = 0
--Heartbeat = 0
--ByeBye = 0
--Hello = 0
--Matrix = 0
--ClipboardText = 0
--ClipboardImage = 0
--Clipboard = 0
--ClipboardDragDrop = 0
--ClipboardDragDropEnd = 0
--ClipboardAsk = 0
--ExplorerDragDrop = 0
--Nil = 0
PackageReceived = MouseWithoutBorders.PackageMonitor
--Keyboard = 0
--Mouse = 0
--Heartbeat = 0
--ByeBye = 0
--Hello = 0
--Matrix = 0
--ClipboardText = 0
--ClipboardImage = 0
--Clipboard = 0
--ClipboardDragDrop = 0
--ClipboardDragDropEnd = 0
--ClipboardAsk = 0
--ExplorerDragDrop = 0
--Nil = 0
PackageID = 0
SensitivePoints = Generic.List`1[Point]
--_items = Point[]
----System.Drawing.Point[] = Point[]: N/A
--_size = 0
--_version = 0
--s_emptyArray = Point[]
----System.Drawing.Point[] = Point[]: N/A
p = {X=0,Y=0}
--x = 0
--y = 0
--Empty = {X=0,Y=0}
<IpcChannelCreated>k__BackingField = False
TOGGLE_ICONS_SIZE = 4
ICON_ONE = 0
@@ -128,34 +55,6 @@ ICON_BIG_CLIPBOARD = 3
ICON_ERROR = 4
JUST_GOT_BACK_FROM_SCREEN_SAVER = 9999
NETWORK_STREAM_BUF_SIZE = 1048576
SymAlBlockSize = 16
PW_LENGTH = 16
PACKAGE_SIZE = 32
PACKAGE_SIZE_EX = 64
WP_PACKAGE_SIZE = 6
KEYEVENTF_KEYDOWN = 1
KEYEVENTF_KEYUP = 2
WH_MOUSE = 7
WH_KEYBOARD = 2
WH_MOUSE_LL = 14
WH_KEYBOARD_LL = 13
WM_MOUSEMOVE = 512
WM_LBUTTONDOWN = 513
WM_RBUTTONDOWN = 516
WM_MBUTTONDOWN = 519
WM_XBUTTONDOWN = 523
WM_LBUTTONUP = 514
WM_RBUTTONUP = 517
WM_MBUTTONUP = 520
WM_XBUTTONUP = 524
WM_LBUTTONDBLCLK = 515
WM_RBUTTONDBLCLK = 518
WM_MBUTTONDBLCLK = 521
WM_MOUSEWHEEL = 522
WM_KEYDOWN = 256
WM_KEYUP = 257
WM_SYSKEYDOWN = 260
WM_SYSKEYUP = 261
[Clipboard]
===============
Comma = System.Char[]
@@ -193,16 +92,51 @@ dragDropStep05ExCalledByIpc = 0
isDropping = False
dragMachine = NONE
<MouseDown>k__BackingField = False
[Encryption]
===============
magicNumber = 0
ran = System.Random
--_impl = System.Random+XoshiroImpl
----_s0 = ????????????
----_s1 = ????????????
----_s2 = ????????????
----_s3 = ????????????
--<Shared>k__BackingField = System.Random+ThreadSafeRandom
InitialIV = ????????????
<GeneratedKey>k__BackingField = False
<KeyCorrupted>k__BackingField = False
LegalKeyDictionary = Concurrent.ConcurrentDictionary`2[System.String,System.Byte[]]
--_tables = Concurrent.ConcurrentDictionary`2+Tables[System.String,System.Byte[]]
----_comparer = Generic.NonRandomizedStringEqualityComparer+OrdinalIgnoreCaseComparer
----_buckets = Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,System.Byte[]][]
------System.Collections.Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,System.Byte[]][] = Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,System.Byte[]][]: N/A
----_fastModBucketsMultiplier = 498560650640798693
----_locks = O[]
------System.Object[] = O[]: N/A
----_countPerLock = 32[]
------[0] = 0
------[1] = 0
------[2] = 0
------[3] = 0
------[4] = 0
------[5] = 0
------[6] = 0
------[7] = 0
--_budget = ????????????
--_growLockArray = True
--_comparerIsDefaultForClasses = False
SymAlBlockSize = 16
PW_LENGTH = 16
[Event]
===============
KeybdPackage = MouseWithoutBorders.DATA
KeybdPackage = MouseWithoutBorders.Core.DATA
--Type = 0
--Id = 0
--Src = NONE
--Des = NONE
--DateTime = 0
--Kd = MouseWithoutBorders.KEYBDDATA
--Md = MouseWithoutBorders.MOUSEDATA
--Kd = MouseWithoutBorders.Core.KEYBDDATA
--Md = MouseWithoutBorders.Core.MOUSEDATA
--Machine1 = NONE
--Machine2 = NONE
--Machine3 = NONE
@@ -212,14 +146,14 @@ KeybdPackage = MouseWithoutBorders.DATA
--machineNameP2 = 0
--machineNameP3 = 0
--machineNameP4 = 0
MousePackage = MouseWithoutBorders.DATA
MousePackage = MouseWithoutBorders.Core.DATA
--Type = 0
--Id = 0
--Src = NONE
--Des = NONE
--DateTime = 0
--Kd = MouseWithoutBorders.KEYBDDATA
--Md = MouseWithoutBorders.MOUSEDATA
--Kd = MouseWithoutBorders.Core.KEYBDDATA
--Md = MouseWithoutBorders.Core.MOUSEDATA
--Machine1 = NONE
--Machine2 = NONE
--Machine3 = NONE
@@ -296,7 +230,7 @@ LogCounter = Concurrent.ConcurrentDictionary`2[System.String,32]
allLogsIndex = 0
lastHour = 0
exceptionCount = 0
lastPackageSent = MouseWithoutBorders.PackageMonitor
lastPackageSent = MouseWithoutBorders.Core.PackageMonitor
--Keyboard = 0
--Mouse = 0
--Heartbeat = 0
@@ -311,7 +245,7 @@ lastPackageSent = MouseWithoutBorders.PackageMonitor
--ClipboardAsk = 0
--ExplorerDragDrop = 0
--Nil = 0
lastPackageReceived = MouseWithoutBorders.PackageMonitor
lastPackageReceived = MouseWithoutBorders.Core.PackageMonitor
--Keyboard = 0
--Mouse = 0
--Heartbeat = 0
@@ -366,6 +300,42 @@ MAX_SOCKET = 8
HEARTBEAT_TIMEOUT = 1500000
SKIP_PIXELS = 1
JUMP_PIXELS = 2
[Package]
===============
PackageSent = MouseWithoutBorders.Core.PackageMonitor
--Keyboard = 0
--Mouse = 0
--Heartbeat = 0
--ByeBye = 0
--Hello = 0
--Matrix = 0
--ClipboardText = 0
--ClipboardImage = 0
--Clipboard = 0
--ClipboardDragDrop = 0
--ClipboardDragDropEnd = 0
--ClipboardAsk = 0
--ExplorerDragDrop = 0
--Nil = 0
PackageReceived = MouseWithoutBorders.Core.PackageMonitor
--Keyboard = 0
--Mouse = 0
--Heartbeat = 0
--ByeBye = 0
--Hello = 0
--Matrix = 0
--ClipboardText = 0
--ClipboardImage = 0
--Clipboard = 0
--ClipboardDragDrop = 0
--ClipboardDragDropEnd = 0
--ClipboardAsk = 0
--ExplorerDragDrop = 0
--Nil = 0
PackageID = 0
PACKAGE_SIZE = 32
PACKAGE_SIZE_EX = 64
WP_PACKAGE_SIZE = 6
[Receiver]
===============
QUEUE_SIZE = 50
@@ -436,3 +406,41 @@ lastStartServiceTime = ????????????
--MinValue = 01/01/0001 00:00:00
--MaxValue = 31/12/9999 23:59:59
--UnixEpoch = 01/01/1970 00:00:00
[WinAPI]
===============
SensitivePoints = Generic.List`1[Point]
--_items = Point[]
----System.Drawing.Point[] = Point[]: N/A
--_size = 0
--_version = 0
--s_emptyArray = Point[]
----System.Drawing.Point[] = Point[]: N/A
p = {X=0,Y=0}
--x = 0
--y = 0
--Empty = {X=0,Y=0}
[WM]
===============
KEYEVENTF_KEYDOWN = 1
KEYEVENTF_KEYUP = 2
WH_MOUSE = 7
WH_KEYBOARD = 2
WH_MOUSE_LL = 14
WH_KEYBOARD_LL = 13
WM_MOUSEMOVE = 512
WM_LBUTTONDOWN = 513
WM_RBUTTONDOWN = 516
WM_MBUTTONDOWN = 519
WM_XBUTTONDOWN = 523
WM_LBUTTONUP = 514
WM_RBUTTONUP = 517
WM_MBUTTONUP = 520
WM_XBUTTONUP = 524
WM_LBUTTONDBLCLK = 515
WM_RBUTTONDBLCLK = 518
WM_MBUTTONDBLCLK = 521
WM_MOUSEWHEEL = 522
WM_KEYDOWN = 256
WM_KEYUP = 257
WM_SYSKEYDOWN = 260
WM_SYSKEYUP = 261

View File

@@ -29,7 +29,7 @@ namespace PowerOCR.Settings
[ImportingConstructor]
public UserSettings(Helpers.IThrottledActionInvoker throttledActionInvoker)
{
_settingsUtils = new SettingsUtils();
_settingsUtils = SettingsUtils.Default;
ActivationShortcut = new SettingItem<string>(DefaultActivationShortcut);
PreferredLanguage = new SettingItem<string>(string.Empty);

View File

@@ -9,7 +9,7 @@ namespace WorkspacesEditor.Utils
public class Settings
{
private const string WorkspacesModuleName = "Workspaces";
private static readonly SettingsUtils _settingsUtils = new();
private static readonly SettingsUtils _settingsUtils = SettingsUtils.Default;
public static WorkspacesSettings ReadSettings()
{

View File

@@ -133,7 +133,7 @@ namespace WorkspacesEditor.ViewModels
_orderByIndex = value;
OnPropertyChanged(new PropertyChangedEventArgs(nameof(WorkspacesView)));
settings.Properties.SortBy = (WorkspacesProperties.SortByProperty)value;
settings.Save(new SettingsUtils());
settings.Save(SettingsUtils.Default);
}
}

View File

@@ -60,7 +60,7 @@ namespace Awake.Core
{
_tokenSource = new CancellationTokenSource();
_stateQueue = [];
ModuleSettings = new SettingsUtils();
ModuleSettings = SettingsUtils.Default;
}
internal static void StartMonitor()

View File

@@ -51,7 +51,7 @@ namespace Awake
private static async Task<int> Main(string[] args)
{
_settingsUtils = new SettingsUtils();
_settingsUtils = SettingsUtils.Default;
LockMutex = new Mutex(true, Core.Constants.AppName, out bool instantiated);

View File

@@ -4,6 +4,4 @@
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
public record DismissMessage()
{
}
public record DismissMessage(bool ForceGoHome = false);

View File

@@ -4,6 +4,4 @@
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
public record NavigateBackMessage(bool FromBackspace = false)
{
}
public record NavigateBackMessage(bool FromBackspace = false);

View File

@@ -0,0 +1,10 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
/// <summary>
/// Used to navigate left in a grid view when pressing the Left arrow key in the SearchBox.
/// </summary>
public record NavigateLeftCommand;

View File

@@ -0,0 +1,10 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
/// <summary>
/// Used to navigate right in a grid view when pressing the Right arrow key in the SearchBox.
/// </summary>
public record NavigateRightCommand;

View File

@@ -378,7 +378,7 @@ public partial class ShellViewModel : ObservableObject,
{
// Reset the palette to the main page and dismiss
GoHome(withAnimation: false, focusSearch: false);
WeakReferenceMessenger.Default.Send<DismissMessage>();
WeakReferenceMessenger.Default.Send(new DismissMessage());
break;
}
@@ -398,7 +398,7 @@ public partial class ShellViewModel : ObservableObject,
case CommandResultKind.Hide:
{
// Keep this page open, but hide the palette.
WeakReferenceMessenger.Default.Send<DismissMessage>();
WeakReferenceMessenger.Default.Send(new DismissMessage());
break;
}

View File

@@ -6,12 +6,12 @@
<!-- For MVVM Toolkit Partial Properties/AOT support -->
<LangVersion>preview</LangVersion>
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\WinUI3Apps\CmdPal\</OutputPath>
<OutputPath>..\..\..\$(Platform)\$(Configuration)\WinUI3Apps\CmdPal\</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<!-- MRT from windows app sdk will search for a pri file with the same name of the module before defaulting to resources.pri -->
<ProjectPriFileName>$(RootNamespace).pri</ProjectPriFileName>
<!-- Disable SA1313 for Primary Constructor fields conflict https://learn.microsoft.com/dotnet/csharp/programming-guide/classes-and-structs/instance-constructors#primary-constructors -->
<NoWarn>SA1313;</NoWarn>
@@ -42,5 +42,5 @@
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
</Project>

Some files were not shown because too many files have changed in this diff Show More