Compare commits

...
155 Commits
Author SHA1 Message Date
Mike Rodriguez d7244969b2 Merge pull request #487 from LizardByte/sunshine
ci: workflow updates
2026-06-22 15:00:18 -07:00
dependabot[bot] 7b33f5e4d2 build(deps): bump actions/checkout from 6.0.3 to 7.0.0 in the github-actions group (#10)
build(deps): bump actions/checkout in the github-actions group

Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout).


Updates `actions/checkout` from 6.0.3 to 7.0.0
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/df4cb1c069e1874edd31b4311f1884172cec0e10...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-19 10:53:54 -04:00
dependabot[bot] de6ba98ee5 build(deps): bump actions/checkout from 6.0.2 to 6.0.3 in the github-actions group (#9)
build(deps): bump actions/checkout in the github-actions group

Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout).


Updates `actions/checkout` from 6.0.2 to 6.0.3
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/de0fac2e4500dabe0009e67214ff5f5447ce83dd...df4cb1c069e1874edd31b4311f1884172cec0e10)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-03 18:50:43 -04:00
David Lane a35fcb8176 chore: Add JetBrains Rider .idea to .gitignore (#7) 2026-05-23 10:17:12 -04:00
David Lane 38c3ec449d chore: migrate wdf to git submodule (#6) 2026-05-23 10:04:17 -04:00
David Lane a9f6065a23 ci: Pin CI runner to windows-2022 (#5) 2026-05-22 22:33:23 -04:00
dependabot[bot] 8a13aa2424 build(deps): bump microsoft/setup-msbuild from 2.0.0 to 3.0.0 (#4)
Bumps [microsoft/setup-msbuild](https://github.com/microsoft/setup-msbuild) from 2.0.0 to 3.0.0.
- [Release notes](https://github.com/microsoft/setup-msbuild/releases)
- [Commits](https://github.com/microsoft/setup-msbuild/compare/6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce...30375c66a4eea26614e0d39710365f22f8b0af57)

---
updated-dependencies:
- dependency-name: microsoft/setup-msbuild
  dependency-version: 3.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-22 22:02:55 -04:00
dependabot[bot] 534d4bcdc8 build(deps): bump the github-actions group with 2 updates (#3)
Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [actions/upload-artifact](https://github.com/actions/upload-artifact).


Updates `actions/checkout` from 4.3.1 to 6.0.2
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/34e114876b0b11c390a56381ad16ebd13914f8d5...de0fac2e4500dabe0009e67214ff5f5447ce83dd)

Updates `actions/upload-artifact` from 4.6.2 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/ea165f8d65b6e75b540449e92b4886f43607fa02...043fb46d1a93c77aae656e7c1c64a875d1fc6a0a)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.2
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-22 22:02:14 -04:00
David Lane ce081a3e10 chore: Add Dependabot configuration for updates
Configure Dependabot for GitHub Actions and Git Submodules with scheduled updates.
2026-05-22 21:59:26 -04:00
LizardByte-bot 7d0a0cec4f chore: update GitHub Actions to use commit hashes (#2) 2026-05-22 21:52:15 -04:00
David Lane 8e85cf2a0c ci: Update workflow for concurrency and branch settings (#1) 2026-05-22 21:48:16 -04:00
Mike Rodriguez a660c72e7c Merge pull request #482 from AndreTheAss/codex/fix-multi-monitor-swapchain-449
Fix multi-monitor swapchain threading for issue #449
2026-05-18 15:49:41 -07:00
Mike Rodriguez 17eed4381b Add related software section to README
Added a section to the README for related software tools with descriptions and links.
2026-05-18 15:44:30 -07:00
andre fc499471c1 Fix multi-monitor swapchain threading for issue #449 2026-04-11 17:57:27 +02:00
Mike Rodriguez 052f0aa300 Fix HDR bit depth for Virtual-Display-Driver 2026-04-07 14:52:31 -07:00
Mike Rodriguez 537b13e300 Merge pull request #473 from clickwithclark/patch-1
docs: Add detailed warning about GPU/chipset driver update conflicts
2026-03-17 19:08:51 -07:00
Clark 4efda4e043 docs: Add detailed warning about GPU/chipset driver update conflicts
Expands on the existing driver update safety warning with:
- Step-by-step prevention instructions
- Detailed Safe Mode recovery steps
- Technical explanation of why this happens
- Real-world system examples

Addresses issue #440
2026-02-13 08:21:55 -04:00
Mike Rodriguez 22e3abfc8e Merge branch 'doc/vdd-driver-update-warning' 2026-02-03 08:34:37 -08:00
Mike Rodriguez 2c33d31caa docs: thank ye4241 for WinGet submission 2026-02-03 08:31:02 -08:00
Mike Rodriguez f2bfc1788d docs: add winget install command 2026-02-03 08:30:15 -08:00
Mike Rodriguez a8cf262b51 Merge pull request #469 from VirtualDrivers/doc/vdd-driver-update-warning
docs: add warning for GPU/chipset driver updates
2026-02-03 07:43:06 -08:00
Mike Rodriguez 7968d8b91d docs: add warning for GPU/chipset driver updates 2026-02-03 07:41:22 -08:00
Mike Rodriguez 36b3485ac0 Merge pull request #464 from fanfan42/fanfan1
Correct README and race condition on silent-install.ps1
2026-01-25 11:32:09 -08:00
François Brunhes aka Fanfan e1dd124574 Correct README and race condition on silent-install.ps1 2026-01-24 19:16:59 +01:00
Mike Rodriguez 2b6c91a00f Revert "initial shader work"
This reverts commit 6cead7c2d9.
2026-01-19 05:03:33 -08:00
Joakim Sandström 6cead7c2d9 initial shader work
all code is remarked
2026-01-18 19:47:58 +01:00
Mike Rodriguez 0d59195756 Improve UMDF include path selection and build config
Enhanced the CI workflow to dynamically select the best available UMDF WDF header version on the runner and pass the UMDF version minor to msbuild. Updated MttVDD.vcxproj to include multiple possible UMDF include paths, improving compatibility with different Windows SDK layouts and ensuring the correct headers are used during builds.
2026-01-08 19:13:15 -08:00
Mike Rodriguez 8a83f4fc0d Remove legacy build workflows and update CI
Deleted the 'build-and-sign-sequential.yml' and 'build-installer.yml' workflows, consolidating build logic. Updated 'ci-validation.yml' to 'Build Virtual Display Driver', now building both x64 and ARM64 VDD in matrix jobs and uploading artifacts, streamlining CI for pull requests and manual runs.
2026-01-08 18:16:32 -08:00
Mike Rodriguez 2fa9d67a65 Remove WDF include directory from project file
Eliminated the reference to the Windows-Driver-Frameworks UMDF 2.15 include directory from all build configurations in MttVDD.vcxproj. This streamlines the include paths and may reflect a change in dependency management or project requirements.
2026-01-08 17:57:44 -08:00
Mike Rodriguez 09d5e393f1 Add IddCx header location debug step to CI workflows
Introduces a PowerShell step in both build-and-sign-sequential and ci-validation workflows to output and verify the location of the IddCx header in the Windows SDK. This aids in diagnosing SDK path issues during CI runs.
2026-01-08 17:28:15 -08:00
Mike Rodriguez 54ee545b43 Update IddCx include path and header casing
Changed the include directive from 'iddcx.h' to 'IddCx.h' in Driver.h to match correct casing. Updated MttVDD.vcxproj to add the Windows SDK IddCx include directory, ensuring the correct versioned path is used for IddCx headers.
2026-01-08 17:24:53 -08:00
Mike Rodriguez eaf7e2163f Add Windows Driver Kit installation to CI workflows
Both build-and-sign-sequential.yml and ci-validation.yml now install the Windows Driver Kit using Chocolatey to provide IddCx headers required for the build process.
2026-01-08 17:12:31 -08:00
Mike Rodriguez c622700ff4 Add UMDF 2.15 WDF headers and improve Windows SDK detection
Added Windows Driver Frameworks (WDF) UMDF 2.15 public headers to ThirdParty/Windows-Driver-Frameworks. Updated GitHub Actions workflows to robustly detect and set Windows SDK paths and versions, and to pass these as MSBuild parameters for driver builds. This improves build reliability and ensures correct SDK usage in CI environments.
2026-01-08 17:05:32 -08:00
Mike Rodriguez 12ceed1b3f Vendor UMDF header and update CI workflows
Added Windows Driver Frameworks UMDF header (wudfwdm.h) under ThirdParty to ensure CI builds work on runners missing Windows Kits/WDK. Removed PowerShell logic from CI workflows that attempted to locate or install UMDF headers, and updated MSBuild invocations to no longer depend on custom environment variables for SDK paths.
2026-01-08 16:34:39 -08:00
Mike Rodriguez ea8c879e5c Improve WDK header detection in CI workflows
Update PowerShell logic in build-and-sign-sequential.yml and ci-validation.yml to handle both flat and versioned WDK header layouts. This ensures compatibility with different runner environments by checking for headers in both possible locations.
2026-01-08 16:22:52 -08:00
Mike Rodriguez fe157ea685 Improve UMDF header detection in CI workflows
Refactored PowerShell logic in build-and-sign-sequential.yml and ci-validation.yml to robustly detect and install UMDF headers (wudfwdm.h). Now attempts installation via winget if headers are missing, improving reliability on runners without preinstalled SDK/WDK.
2026-01-08 16:16:45 -08:00
Mike Rodriguez e3924aeb5e Detect and use correct Windows SDK version in CI builds
Added steps to both build-and-sign-sequential.yml and ci-validation.yml workflows to dynamically detect the installed Windows Kits version and set the appropriate MSBuild properties for WindowsSdkDir and WindowsTargetPlatformVersion. This ensures the correct SDK is used for driver builds, improving reliability across environments. Also simplified the SignPath submission step condition.
2026-01-08 16:09:11 -08:00
Mike Rodriguez 0a31eaaacf Refactor and add CI workflows for build and validation
Refactored the build-and-sign-sequential workflow to simplify Windows SDK/WDK installation, update MSBuild setup, and improve installer build steps. Added new workflows: build-installer.yml for building the installer independently, and ci-validation.yml for fast CI validation on PRs and pushes. These changes streamline CI processes and separate installer and validation logic for better maintainability.
2026-01-08 15:55:18 -08:00
Mike Rodriguez 38b6e5117b Update build-and-sign-sequential.yml 2026-01-08 14:17:18 -08:00
Mike Rodriguez 642ee285ff Improve Windows Kits detection and project includes
Added automatic detection of Windows Kits version and SDK directory in the build workflow, passing them to msbuild for driver builds. Removed manual inclusion of wudfwdm.h from the project files to rely on SDK headers, streamlining build configuration and reducing local dependencies.
2026-01-08 14:01:46 -08:00
Mike Rodriguez 7290cd6d87 README: add recent changelog (last 5 feature updates) 2026-01-08 12:59:01 -08:00
Mike Rodriguez fea4d9e4e5 Adapter selection: use explicit DEVPKEY_Device_Luid definition 2026-01-08 12:43:45 -08:00
Mike Rodriguez 13d382731d Build: use C++17 in Release configs 2026-01-08 12:43:09 -08:00
Mike Rodriguez b654504edf Link setupapi.lib (required for PCI bus LUID resolution) 2026-01-08 12:36:47 -08:00
Mike Rodriguez cac37672da Adapter selection: allow LUID resolution by PCI bus 2026-01-08 12:30:17 -08:00
Mike Rodriguez 498c37b30d Fix newline at EOF in Community Scripts README 2026-01-08 12:11:53 -08:00
Joakim Sandström 4bdebe23f2 Merge pull request #442 from Efreak/master
Format community scripts readme to add links and make it readable in github.
2025-11-26 23:18:52 +01:00
efreak 472b2f2a32 Add links to the scripts
Links are referenced at bottom to keep raw text readable.
2025-11-17 14:31:31 -08:00
efreak 3e8d2115c0 Make a table for scripts for readability
On github website, single line-breaks are ignored, causing the list to turn into a paragraph.
This makes it more readable both in the browser and as raw text by aligning the descriptions and making it a table in the browser.
2025-11-17 14:17:26 -08:00
Mike Rodriguez 63f9285461 Revert "Merge pull request #413 from zjoasan/zjoasan-adapteroption-patch1"
This reverts commit 05ae18d104, reversing
changes made to 06b2dbd7d4.
2025-11-09 05:00:51 -08:00
Mike Rodriguez b642ef64d8 Merge pull request #430 from Harinath1314-tech/master
Add VDD Toggle Utility - Batch script for easy enable/disable
2025-10-29 11:27:52 -07:00
Mike Rodriguez 7267835157 Merge pull request #426 from fanfan42/fanfan1
Change devcon to nefcon for silent install community script
2025-10-29 11:26:39 -07:00
Mike Rodriguez 05ae18d104 Merge pull request #413 from zjoasan/zjoasan-adapteroption-patch1
DeviceID, pcislot friendly name
2025-10-29 11:25:54 -07:00
Harinath1314-tech fd8700f636 Create README.md
Add VDD Toggle Utility - Batch script for toggling Virtual Display Driver
2025-10-28 12:53:00 +05:30
François Brunhes aka Fanfan 88916eca0a Change devcon to nefcon for silent install community script 2025-10-17 21:25:14 +02:00
Mike Rodriguez 06b2dbd7d4 Merge pull request #419 from fanfan42/fanfan1
The silent install script is really silent
2025-09-27 15:39:50 -07:00
François Brunhes aka Fanfan 830de3f2aa The silent install script is really silent 2025-09-27 23:32:50 +02:00
Joakim Sandström 7233822630 Update README.md
Added some links to Wiki and Community scripts, and referring to default location for vdd_settings.xml
2025-09-27 17:48:36 +02:00
Mike Rodriguez bccc901b1b Merge pull request #410 from goodusername123/README-table
README.md: Replace table image with actual table
2025-09-08 22:33:29 -07:00
Joakim Sandström 2a18a0b594 DeviceID, pcislot friendly anme
This is untested but "should work" logical code for a first implementation of "dual identical adapter cards"
2025-09-08 19:32:35 +02:00
goodusername123 7becdd43c0 README.md: Replace table image with real table 2025-08-27 04:27:29 -05:00
Mike Rodriguez 3917232ae1 Update build-and-sign-sequential.yml 2025-08-17 17:24:23 -07:00
Mike Rodriguez b5383e859d Update build-and-sign-sequential.yml 2025-08-17 16:59:29 -07:00
Mike Rodriguez 93c6fff4f5 Update build-and-sign-sequential.yml 2025-08-17 16:47:25 -07:00
Mike Rodriguez 74477f745d Update build-and-sign-sequential.yml 2025-08-17 16:10:22 -07:00
Mike Rodriguez d0f8a028c6 Update build-and-sign-sequential.yml 2025-08-17 15:58:21 -07:00
Mike Rodriguez c585ee93cf Build Sequential 2025-08-17 15:49:59 -07:00
Mike Rodriguez b9acacd40c Update build-and-sign-sequential.yml 2025-08-17 15:24:18 -07:00
Mike Rodriguez 0cccd7a14d YML Additions 2025-08-17 14:53:21 -07:00
Mike Rodriguez 89b7b4477d Update build-and-sign-sequential.yml 2025-08-17 14:46:07 -07:00
Mike Rodriguez a01ecfd460 Update build-and-sign-sequential.yml 2025-08-17 14:22:35 -07:00
Mike Rodriguez 587f99c8c3 Update build-and-sign-sequential.yml 2025-08-17 14:01:26 -07:00
Mike Rodriguez dd198e508e Update build-and-sign-sequential.yml 2025-08-17 13:54:05 -07:00
Mike Rodriguez 4b6ba2246e Update version.xml 2025-08-17 08:52:01 -07:00
Mike Rodriguez c928fa9251 Added GettIddCx Source 2025-08-17 04:46:18 -07:00
Mike Rodriguez d5a4466425 Update vdd_settings.xml 2025-08-17 04:44:54 -07:00
Mike Rodriguez a602844e89 Added version.xml for app integration. 2025-08-16 03:02:16 -07:00
Mike Rodriguez 92203a544c EDID Integration
🔌 EDID Profile Integration

  - Automatic Monitor Configuration: Loads settings from monitor_profile.xml
  - Priority System: Manual settings override EDID when needed
  - Graceful Fallback: Uses manual config if EDID loading fails

  🌈 HDR10 Support

  - SMPTE ST.2086 Compliance: Industry-standard HDR metadata
  - Color Primaries: RGB chromaticity coordinates + white point
  - Luminance Management: Min/max mastering + content light levels

  🎨 Advanced Color Processing

  - Multi Color Space: sRGB, DCI-P3, Rec.2020, Adobe RGB support
  - Gamma Correction: Customizable gamma curves with 3x4 matrix transforms
  - FP16 Pipeline: High-precision color calculations

  📺 Intelligent Mode Management

  - EDID Mode Generation: Automatic resolution extraction from profiles
  - Advanced Filtering: Refresh rate, resolution, and aspect ratio constraints
  - Mode Optimization: Duplicate removal and performance tuning

  🛡️ Production Quality

  - Comprehensive Validation: 4-test diagnostic suite with real-time monitoring
  - Configuration Sanitization: Automatic correction of invalid settings
  - Emergency Fallback: sRGB/D65 defaults for system stability
  - Performance Monitoring: 10ms threshold tracking for optimal performance

  🔧 File Structure

  C:\VirtualDisplayDriver\
  ├── vdd_settings.xml          (Required - Main configuration)
  └── EDID\monitor_profile.xml  (Optional - EDID profile data)

  🙏 Acknowledgments

  - MikeTheTech - For implementing this comprehensive EDID integration into the driver codebase.
  - Jocke - For developing the EDID parser that generates the monitor profile data used by this system.
2025-08-14 15:36:09 -07:00
Mike Rodriguez 61ae3fbd07 Merge pull request #400 from tanakamasayuki/patch-1
Update URL
2025-08-13 23:06:49 -07:00
Mike Rodriguez 3750c5ed4f Performance Optimization
Thread Management

  - Added: Explicit thread completion waiting in IndirectDeviceContext::AssignSwapChain()
  - Fixed: SwapChainProcessor destructor race conditions
  - Improved: Thread lifecycle logging and diagnostics

  Resource Management

  - Changed: Device cache from std::map<LUID, std::weak_ptr<Direct3DDevice>> to std::map<LUID,
  std::shared_ptr<Direct3DDevice>>
  - Added: Comprehensive LUID-based logging for device cache operations
  - Optimized: Cleanup frequency reduced from every assignment to every 10th assignment

  Error Handling

  - Implemented: 5-attempt retry limit with exponential backoff for DXGI_ERROR_ACCESS_LOST
  - Added: Device integrity validation before swap chain operations
  - Enhanced: Error logging with detailed HRESULT codes and context
2025-08-13 08:49:45 -07:00
TANAKA Masayuki 506791639d Update URL
https://github.com/VirtualDisplay/
404
2025-08-06 13:36:55 +09:00
Mike Rodriguez 14d1e344d7 Update README.md 2025-07-28 20:57:28 -07:00
Mike Rodriguez d437ebc9b4 Merge pull request #391 from VirtualDrivers/PS-Get_Disp_Num-update
Added a pause for VDC execution
2025-07-23 08:16:43 -07:00
Joakim Sandström 5aa453b3c0 Added a pause for VDC execution
Documented the script a bit, removed non essential header and added "Press any key..."-pause for VDC execution, . 
Now you get a clear screen, example 8:
 \\.\DISPLAY8 
Press any key to continue ...
2025-07-18 11:36:56 +02:00
Mike Rodriguez 0a095d4b76 Delete .github/workflows/build-fix.ps1 2025-07-14 16:50:28 -07:00
Mike Rodriguez 8e874f0bed Delete .github/workflows/compile.yml 2025-07-14 16:50:02 -07:00
Mike Rodriguez 33ea391a91 Delete .github/workflows/build-and-sign-all.yml 2025-07-14 16:49:47 -07:00
Mike Rodriguez 5b9822bc0b Delete .github/workflows/SubmitAllToSignPath 2025-07-14 16:49:36 -07:00
Mike Rodriguez 8c9b0f8c9a Delete .github/workflows/Submit-To-SignPath.yml 2025-07-14 16:49:24 -07:00
Mike Rodriguez 0969263ba1 Update build-and-sign-sequential.yml 2025-07-14 16:15:06 -07:00
Mike Rodriguez d4964dbcfd Add files via upload 2025-07-14 15:48:17 -07:00
Mike Rodriguez 25eb449ee6 Update build-and-sign-all.yml 2025-07-14 15:36:00 -07:00
Mike Rodriguez 05f279346f Update build-and-sign-all.yml 2025-07-14 15:07:17 -07:00
Mike Rodriguez 9e8f62ab3c Update build-and-sign-all.yml 2025-07-14 14:43:19 -07:00
Mike Rodriguez ac0c52e8a5 Update build-and-sign-all.yml 2025-07-14 14:12:43 -07:00
Mike Rodriguez 0f2c9106be Update build-and-sign-all.yml 2025-07-14 14:05:33 -07:00
Mike Rodriguez 724bec4115 Update build-and-sign-all.yml 2025-07-14 13:52:06 -07:00
Mike Rodriguez 8e76e9dc14 Update build-and-sign-all.yml 2025-07-14 13:41:58 -07:00
Mike Rodriguez b8a6fe0fb8 Add files via upload 2025-07-14 13:34:59 -07:00
Mike Rodriguez 3650e70d02 Merge pull request #379 from PanicTitan/master
New script to manager the virtual driver in cli
2025-06-17 05:11:12 -07:00
Mike Rodriguez 24c740857a Merge pull request #367 from zjoasan/patch-1
Update scripts README.md
2025-06-17 05:10:50 -07:00
PanicTitan e851bf9a3b Create virtual-driver-manager.ps1
A script to install, uninstall, enable, disable, toggle, and check the status of the driver. Based on current Community Scripts with Silent options and json outs for use in other programs,
2025-06-17 00:47:56 -03:00
Mike Rodriguez b49fc4017e Remove VAD workflows temporarily. 2025-05-15 23:27:04 -07:00
Mike Rodriguez 1dde89134f Worflows 2025-05-15 23:14:50 -07:00
Mike Rodriguez c53bd3f66b Update VAD-compile-and-sign.yml 2025-05-15 22:22:44 -07:00
Mike Rodriguez 8ea77f7f06 Update VAD-compile-and-sign.yml 2025-05-15 22:02:26 -07:00
Mike Rodriguez 646c2d833f Update VAD-compile-and-sign.yml 2025-05-15 21:38:26 -07:00
Mike Rodriguez e19d8a82b9 Oops 2025-05-15 21:21:17 -07:00
Mike Rodriguez d4f2eba005 .CAT signing adjustments. 2025-05-15 21:01:02 -07:00
Mike Rodriguez 54d3113196 Fixed $packageDir 2025-05-15 19:54:44 -07:00
Mike Rodriguez 03b08e474f Ignore restart required. 2025-05-15 19:34:58 -07:00
Mike Rodriguez 9eeb8fec55 Added VAD for building. 2025-05-15 18:46:51 -07:00
Mike Rodriguez 56a78f9214 Update README.md 2025-05-08 02:35:22 -07:00
Mike Rodriguez dd1fa14bc9 Update README.md 2025-05-08 02:31:51 -07:00
Mike Rodriguez 36461d5022 Update README.md 2025-05-08 02:30:15 -07:00
Mike Rodriguez d7a0d3ec33 Update workflow. 2025-05-08 02:11:45 -07:00
Mike Rodriguez 0b8f896008 Workflow update/test. 2025-05-08 01:24:27 -07:00
Joakim Sandström aaa12df16d Update README.md
Added a short description for most scripts.
2025-05-06 11:57:41 +02:00
Mike Rodriguez cae46b429d Update MttVDD.vcxproj 2025-05-02 23:56:31 -07:00
Mike Rodriguez 1995e6de2b Revert "Test"
This reverts commit c6b1e893ec.
2025-05-02 23:42:58 -07:00
Mike Rodriguez c6b1e893ec Test 2025-05-02 23:41:42 -07:00
Mike Rodriguez 3a1871fd23 Merge pull request #352 from lvde0/silent-install-script
Add silent-install script
2025-05-01 05:36:40 -07:00
lvde0 3f6e54631b Add silent-install script 2025-04-24 10:29:37 +02:00
Mike Rodriguez 96c662be6c Update README.md 2025-03-26 11:29:42 -07:00
Mike Rodriguez 3a20ccb5e2 Update compile.yml 2025-03-22 11:26:27 -07:00
Mike Rodriguez 5d2892ab0b Merge pull request #326 from VirtualDisplay/itsmikethetech-patch-6
Update compile.yml
2025-03-22 11:15:06 -07:00
Mike Rodriguez e87194f972 Update compile.yml 2025-03-22 11:12:07 -07:00
Bud 0505e34539 Update README.md 2025-03-15 05:17:56 +00:00
Bud 9fb159bb53 Oops
Fixed
2025-03-14 02:33:48 +00:00
Bud f0bdbfd4a0 Added workflow for signing installer too
Sign Installer with seperate policy slug

If this isnt allowed, then Mike this is on you. You told me to do the same repo before....
2025-03-14 02:32:45 +00:00
Bud 94b35105e4 Create Question.yml 2025-02-27 20:06:30 +00:00
Bud 322e36a613 Create HelpWanted.yml 2025-02-27 20:03:06 +00:00
Bud 80b461b02f Update bug_report.yml
Added driver version 
Added device specs, optional
2025-02-27 19:55:43 +00:00
bud3699 00e43b5d1f restructure of xml 2025-02-27 17:01:46 +00:00
bud3699 e3f58b629a Added support for changing colour format
- Added support for changing colour format in xml
Supported formats:
		RGB
		YCbCr444
		YCbCr422
		YCbCr420

- XML Grouped
2025-02-27 16:59:52 +00:00
bud3699 e4bc40252a Xor Support level added
THIS SHOULD NOT BE CHANGED UNLESS YOU KNOW WHAT YOU'RE DOING
2025-02-27 14:46:32 +00:00
bud3699 976dd165f6 Configurable Cursor Support
- This commit is for the people who need more advanced cursor configuration support
2025-02-27 14:14:52 +00:00
bud3699 5281cef87f Give option to dis-allow logs through the pipe 2025-02-27 13:22:12 +00:00
bud3699 3a500d8773 Remove duplicate includes 2025-02-27 13:13:16 +00:00
Mike Rodriguez 888f3ae2d2 Merge pull request #298 from VirtualDisplay/itsmikethetech-patch-5
Update README.md
2025-02-20 01:48:26 -08:00
Mike Rodriguez 3565152e07 Update README.md 2025-02-20 01:48:03 -08:00
Mike Rodriguez cd1445427b Update README.md 2025-02-20 01:44:02 -08:00
Mike Rodriguez 64602d2aaa Update readme, added dev credits and icons. (#297)
* Update readme, added dev credits and icons.
2025-02-20 09:37:37 +00:00
Kyle Yee ef87af27dc Fixed typo in README Instructions (#296) 2025-02-20 09:36:31 +00:00
Mike Rodriguez 888387fc72 Merge pull request #282 from VirtualDisplay/itsmikethetech-patch-2
Fixed star history chart.
2025-02-01 07:13:39 -08:00
Mike Rodriguez 15d229200b Merge pull request #283 from jotopo/feature/update-community-scripts
Update the community scripts.
2025-02-01 07:13:21 -08:00
Thijs 0318e5399a Update the community scripts.
- FIX: selecting display
- FEAT: add params with validations where necessary.
- FEAT: add dependency checking
2025-02-01 16:08:54 +01:00
Mike Rodriguez 74ca716296 Update README.md 2025-02-01 06:14:58 -08:00
Mike Rodriguez 44e199935b Merge pull request #281 from zjoasan/master
Module_install.bat and get_disp_num.p1 (DISPLAY#)
2025-02-01 03:53:41 -08:00
Joakim Sandström 69359ec35c Module_install.bat and get_disp_num.p1 (DISPLAY#)
Since dep_fix.ps1 seem less then reliable, I've created a bat file that installs the needed powershell modules. It needs admin privs. to install to all users on the machine. I'm planning on running this .bat during the installer in case the user choose to install the scripts.

The get_disp_num.ps1 is for those users depending on \\\\.\\DISPLAY number to get the right display for their scripting needs in their "automation"
2025-02-01 12:04:17 +01:00
BudandMike Rodriguez c87b0c4f89 Update for renamed repo. (#247)
Co-authored-by: Mike Rodriguez <contact@mikethetech.com>
2025-01-05 18:07:49 +00:00
Mike Rodriguez dcb511f188 Cleanup 2025-01-05 02:20:28 -08:00
Bud 52bbd2d97c Update bug_report.yml
- Removed log only for beta
2025-01-04 00:17:16 +00:00
Nevryk SandBud 8644ed559d Add Note About Microsoft Visual C++ Redistributable Requirement to README (#237)
Added note for Visual C++ redistributable dependency. This caused a "vcruntime140.dll" error on launch of the vdd companion.

---------

Co-authored-by: Bud
2025-01-03 00:18:30 +00:00
Bud 9ac6074136 Update README.md 2024-12-24 17:51:19 +00:00
174 changed files with 23362 additions and 3697 deletions

No files matched your search

+120
View File
@@ -0,0 +1,120 @@
name: Help Request
description: Request help with an issue.
title: "[Help]: "
labels: ["help wanted", "triage"]
assignees: ["zjoasan", "bud3699", "itsmikethetech"]
body:
- type: markdown
attributes:
value: |
Thanks for reaching out! Please provide as much detail as possible to help us assist you.
- type: dropdown
id: OS
attributes:
label: Which OS?
description: What version of Windows are you using?
options:
- Win11 Pro
- Win11 Home
- Win10 Pro
- Win10 Home
- Other..
default: 0
validations:
required: true
- type: dropdown
id: Version
attributes:
label: Which release?
description: What version of Windows are you running?
options:
- 24H2
- 23H2
- 22H2
- 21H2
- 1809
- 1607
- 1507
- Other..
default: 0
validations:
required: true
- type: markdown
attributes:
value: |
If you need help finding your Windows version, go to Settings -> System -> About.
- type: input
id: driver-version
attributes:
label: Driver Version
description: What driver version are you using?
placeholder: Enter driver version here.
validations:
required: true
- type: textarea
id: device-specs
attributes:
label: Device Specifications
description: Provide details about your hardware. This is to help us indentify whether its a potential hardware incompatibility. This isnt needed but helps.
placeholder: |
CPU: Example CPU
GPU: Example GPU
RAM: Example Ram
MOBO: Example Motherboard
validations:
required: false
- type: textarea
id: issue-info
attributes:
label: What issue are you experiencing or what do you need help with?
description: Describe the issue you need help with.
placeholder: |
Provide a clear and concise description of the help you need.
validations:
required: true
- type: textarea
id: troubleshooting-steps
attributes:
label: Troubleshooting steps taken
description: What have you tried so far to fix the issue?
placeholder: |
List steps you've taken to resolve/assist the problem.
validations:
required: false
- type: textarea
id: expected-outcome
attributes:
label: Expected outcome
description: What were you expecting/want to happen?
placeholder: |
Describe the behavior you expected/want.
validations:
required: false
- type: textarea
id: additional-info
attributes:
label: Additional information
description: Any extra details that might help us assist you.
placeholder: |
Provide any relevant logs, screenshots, or error messages.
validations:
required: false
- type: input
id: contact
attributes:
label: Contact Details
description: How can we reach you if we need more information?
placeholder: ex. email@example.com
validations:
required: false
+44
View File
@@ -0,0 +1,44 @@
name: Question
description: Ask a general question.
title: "[Question]: "
labels: ["question", "triage"]
assignees: ["zjoasan", "bud3699", "itsmikethetech"]
body:
- type: markdown
attributes:
value: |
Thanks for reaching out! Please provide as much detail as possible to help us understand your question.
- type: textarea
id: question-info
attributes:
label: What is your question?
description: Provide details about your question.
placeholder: |
Describe your question clearly so we can assist you effectively.
validations:
required: true
- type: textarea
id: additional-info
attributes:
label: Additional information
description: Any extra details that might help us answer your question.
placeholder: |
Provide any relevant context, screenshots, or references.
validations:
required: false
- type: input
id: contact
attributes:
label: Contact Details
description: How can we reach you if we need more information?
placeholder: ex. email@example.com
validations:
required: false
+37 -7
View File
@@ -9,6 +9,7 @@ body:
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: dropdown
id: OS
attributes:
@@ -23,6 +24,7 @@ body:
default: 0
validations:
required: true
- type: dropdown
id: Version
attributes:
@@ -40,10 +42,34 @@ body:
default: 0
validations:
required: true
- type: markdown
attributes:
value: |
If you struggle finding windows edition and version, Go to settings -> system -> about. Under windows specifications.
If you struggle finding Windows edition and version, go to Settings -> System -> About. Under Windows specifications.
- type: input
id: driver-version
attributes:
label: Driver Version
description: What driver version are you using?
placeholder: Enter driver version here.
validations:
required: true
- type: textarea
id: device-specs
attributes:
label: Device Specifications
description: Provide details about your hardware. This is to help us indentify whether its a potential hardware issue.
placeholder: |
CPU: Example CPU
GPU: Example GPU
RAM: Example Ram
MOBO: Example Motherboard
validations:
required: false
- type: textarea
id: bug-info
attributes:
@@ -54,16 +80,20 @@ body:
A clear and concise description of what the bug is.
validations:
required: true
- type: textarea
id: reproduce-info
attributes:
label: Steps to reproduce
description: And if you can how to reproduce
description: And if you can, how to reproduce
placeholder: |
Tell us how to reproduce!
Go to '...', 2. Click on '....', and so on.
1. Go to '...'
2. Click on '....'
3. Observe issue.
validations:
required: false
- type: textarea
id: expected-info
attributes:
@@ -71,14 +101,15 @@ body:
description: Please inform us about expected behavior.
placeholder: |
Description of behavior!
When i Clicked...
When I clicked...
validations:
required: false
- type: textarea
id: log-file
attributes:
label: Log File (Beta Only)
description: Please attach the log file to help us diagnose the issue. You can drag and drop the file here or click to upload. The log can be retrieved by enabling the log file in the xml then restarting the driver.
label: Log File
description: Please attach the log file to help us diagnose the issue. You can drag and drop the file here or click to upload. The log can be retrieved by enabling the log file in the XML, then restarting the driver.
placeholder: Drag and drop the log file here or click to upload.
validations:
required: false
@@ -91,4 +122,3 @@ body:
placeholder: ex. email@example.com
validations:
required: false
+26
View File
@@ -0,0 +1,26 @@
---
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
rebase-strategy: disabled
schedule:
interval: "cron"
cronjob: "0 2 * * *"
timezone: "America/New_York"
open-pull-requests-limit: 10
groups:
github-actions:
applies-to: version-updates
patterns:
- "actions/*"
- "github/*"
- package-ecosystem: "gitsubmodule"
directory: "/"
rebase-strategy: disabled
schedule:
interval: "cron"
cronjob: "30 2 * * *"
timezone: "America/New_York"
open-pull-requests-limit: 10
-141
View File
@@ -1,141 +0,0 @@
name: Virtual Display Driver Signpath Request
on:
workflow_dispatch:
jobs:
build:
runs-on: windows-latest
strategy:
matrix:
configuration: [Release]
platform: [x64, ARM64]
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v1
- name: Check Chocolatey installation
run: choco --version
- name: Install Visual Studio 2022 dependencies
run: |
choco install visualstudio2022-workload-manageddesktop -y
if ($LASTEXITCODE -ne 0) { exit 1 }
choco install visualstudio2022-workload-nativedesktop -y
if ($LASTEXITCODE -ne 0) { exit 1 }
choco install visualstudio2022-workload-vctools -y
if ($LASTEXITCODE -ne 0) { exit 1 }
choco install windowsdriverkit11 -y
if ($LASTEXITCODE -ne 0) { exit 1 }
- name: Build the driver
run: |
msbuild "Virtual Display Driver (HDR)/MTTVDD.sln" /p:Configuration=${{ matrix.configuration }} /p:Platform=${{ matrix.platform }}
- name: List build directory
run: dir "Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD"
- name: Upload built driver
id: upload_artifact
uses: actions/upload-artifact@v4
with:
name: Built-Driver-${{ matrix.configuration }}-${{ matrix.platform }}
path: |
Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD\MttVDD.dll
Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD\MttVDD.inf
Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD\mttvdd.cat
Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD\vdd_settings.xml
- name: Generate release tag
id: generate_tag
run: |
$releaseTag = (Get-Date).ToString('yy.MM.dd')
echo "RELEASE_TAG=$releaseTag" >> $env:GITHUB_ENV
- name: Show generated release tag
run: |
echo "Generated Release Tag: ${{ env.RELEASE_TAG }}"
- name: Verify Built Artifacts
run: dir 'Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD'
- name: Submit signing request to SignPath
id: signpath_request
uses: signpath/github-action-submit-signing-request@v1
with:
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
organization-id: '${{ vars.SIGNPATH_ORG_ID }}'
project-slug: '${{ vars.SIGNPATH_PROJECT_SLUG }}'
signing-policy-slug: '${{ vars.SIGNPATH_POLICY_SLUG }}'
github-artifact-id: '${{ steps.upload_artifact.outputs.artifact-id }}'
wait-for-completion: true
output-artifact-directory: '${{ vars.SIGNPATH_OUTPUT_DIR }}'
parameters: |
Version: ${{ toJSON(matrix.configuration) }}
Release_Tag: "${{ env.RELEASE_TAG }}"
- name: Verify Signed Artifacts
run: dir '${{ vars.SIGNPATH_OUTPUT_DIR }}'
- name: Upload signed artifacts
id: upload_signed_artifacts
uses: actions/upload-artifact@v4
with:
name: Signed-Driver-${{ matrix.configuration }}-${{ matrix.platform }}
path: |
${{ vars.SIGNPATH_OUTPUT_DIR }}\MttVDD.dll
${{ vars.SIGNPATH_OUTPUT_DIR }}\MttVDD.inf
${{ vars.SIGNPATH_OUTPUT_DIR }}\mttvdd.cat
${{ vars.SIGNPATH_OUTPUT_DIR }}\vdd_settings.xml
- name: Prepare Setup Repository
run: |
git clone https://${{ secrets.READ_REPO }}@github.com/VirtualDisplay/vdd-innosetupscript.git inno-setup
- name: Prepare Setup
run: |
copy "${{ vars.SIGNPATH_OUTPUT_DIR }}\*" inno-setup\input\
$platform = "${{ matrix.platform }}"
(Get-Content "inno-setup\Setup.iss") |
ForEach-Object { $_ -replace '1.0.0', '${{ env.RELEASE_TAG }}' } |
Set-Content "inno-setup\Setup.iss"
if ($platform -eq 'ARM64') {
(Get-Content "inno-setup\Setup.iss") |
ForEach-Object { $_ -replace 'x64compatible', 'arm64' } |
Set-Content "inno-setup\Setup.iss"
(Get-Content "inno-setup\Setup.iss") |
ForEach-Object { $_ -replace '-x64', '-arm64' } |
Set-Content "inno-setup\Setup.iss"
if (Test-Path "inno-setup\input\Companion\VDDSysTray.exe") {Remove-Item "inno-setup\input\Companion\VDDSysTray.exe"}
copy "inno-setup\input\Companion\arm64\VDDSysTray.exe" "inno-setup\input\Companion\"
}
- name: Compile Installer
uses: Minionguyjpro/Inno-Setup-Action@v1.2.2
with:
path: inno-setup\Setup.iss
options: /O+
- name: Upload Installer as artifact
uses: actions/upload-artifact@v4
with:
name: Installer-${{ matrix.configuration }}-${{ matrix.platform }}
path: inno-setup\output\*.exe
celebrate:
runs-on: ubuntu-latest
steps:
- name: Celebrate
run: |
echo "Bud is a god, also hi if you're looking at this!"
+150
View File
@@ -0,0 +1,150 @@
---
name: Build Virtual Display Driver
on:
pull_request:
push:
branches: [ main, master ]
paths-ignore:
- '**.md'
- 'docs/**'
- 'LICENSE*'
workflow_dispatch:
concurrency:
group: "${{ github.workflow }}-${{ github.ref }}"
cancel-in-progress: true
env:
BUILD_CONFIGURATION: Release
VDD_SOLUTION: Virtual Display Driver (HDR)/MttVDD.sln
permissions:
contents: read
jobs:
build:
# The WDK driver build is validated against VS 2022; windows-latest is moving to VS 2026.
runs-on: windows-2022
strategy:
fail-fast: false
matrix:
platform: [x64, ARM64]
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
submodules: true
- name: Setup MSBuild
uses: microsoft/setup-msbuild@30375c66a4eea26614e0d39710365f22f8b0af57 # v3.0.0
- name: Install Windows Driver Kit (IddCx headers)
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
choco install windowsdriverkit11 -y --no-progress
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
- name: Detect Windows SDK (windows.h)
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$kitsRoot = $null
try {
$kitsRoot = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -Name "KitsRoot10" -ErrorAction Stop).KitsRoot10
} catch {
$kitsRoot = Join-Path ${env:ProgramFiles(x86)} "Windows Kits\10\"
}
if (-not $kitsRoot -or -not (Test-Path $kitsRoot)) {
throw "Windows Kits root not found: $kitsRoot"
}
$includeRoot = Join-Path $kitsRoot "Include"
if (-not (Test-Path $includeRoot)) {
throw "Windows Kits Include directory not found: $includeRoot"
}
$best =
Get-ChildItem -Path $includeRoot -Directory -ErrorAction SilentlyContinue |
Where-Object { $_.Name -match '^\d+\.\d+\.\d+\.\d+$' } |
Where-Object { Test-Path (Join-Path $_.FullName "um\Windows.h") } |
Sort-Object -Property Name -Descending |
Select-Object -First 1
if (-not $best) {
throw "Could not find an SDK version directory containing um\\Windows.h under: $includeRoot"
}
$sdkVersion = $best.Name
Write-Output "Using WindowsSdkDir: $kitsRoot"
Write-Output "Using WindowsTargetPlatformVersion: $sdkVersion"
"WINDOWS_SDK_DIR=$kitsRoot" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
"WINDOWS_TARGET_PLATFORM_VERSION=$sdkVersion" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
- name: Build VDD (${{ matrix.platform }})
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$sln = "${{ env.VDD_SOLUTION }}"
if (-not (Test-Path $sln)) { throw "VDD solution file not found at: $sln" }
# Pick an available UMDF WDF header version on the runner.
# Kits can be laid out either versioned:
# Include\<sdk>\wdf\umdf\2.xx
# or unversioned:
# Include\wdf\umdf\2.xx
$umdfRoots = @(
(Join-Path $env:WINDOWS_SDK_DIR ("Include\" + $env:WINDOWS_TARGET_PLATFORM_VERSION + "\wdf\umdf")),
(Join-Path $env:WINDOWS_SDK_DIR "Include\wdf\umdf")
) | Where-Object { Test-Path $_ }
if (-not $umdfRoots -or $umdfRoots.Count -eq 0) {
throw "UMDF WDF include root not found under $env:WINDOWS_SDK_DIR (tried versioned + unversioned layouts)"
}
$umdfBest =
$umdfRoots |
ForEach-Object { Get-ChildItem -Path $_ -Directory -ErrorAction SilentlyContinue } |
Where-Object { $_.Name -match '^\d+\.\d+$' } |
Sort-Object -Property Name -Descending |
Select-Object -First 1
if (-not $umdfBest) { throw "No UMDF version directories found under: $($umdfRoots -join ', ')" }
$umdfMinor = ($umdfBest.Name -split '\.')[1]
Write-Output "Using UMDF version: $($umdfBest.Name) (minor=$umdfMinor) from $($umdfBest.FullName)"
msbuild $sln `
/m `
/t:Build `
/p:Configuration="${{ env.BUILD_CONFIGURATION }}" `
/p:Platform="${{ matrix.platform }}" `
/p:WindowsSdkDir="$env:WINDOWS_SDK_DIR" `
/p:WindowsTargetPlatformVersion="$env:WINDOWS_TARGET_PLATFORM_VERSION" `
/p:UMDF_VERSION_MINOR="$umdfMinor" `
/p:EnableInfVerif=false `
/p:RunApiValidator=false `
/verbosity:minimal
- name: Collect outputs
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$outDir = "Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ env.BUILD_CONFIGURATION }}\MttVDD"
if (-not (Test-Path $outDir)) { throw "Build output directory not found: $outDir" }
$dest = "artifacts\VDD\${{ matrix.platform }}"
New-Item -ItemType Directory -Path $dest -Force | Out-Null
Copy-Item "$outDir\*" -Destination $dest -Recurse -Force
- name: Upload artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: VDD-${{ matrix.platform }}-${{ env.BUILD_CONFIGURATION }}
path: artifacts/VDD/${{ matrix.platform }}/
if-no-files-found: error
-73
View File
@@ -1,73 +0,0 @@
name: Virtual Display Driver Building
on:
workflow_dispatch:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
build:
runs-on: windows-latest
strategy:
matrix:
configuration: [Debug, Release]
platform: [x64, ARM64]
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v1
- name: Check Chocolatey installation
run: choco --version
- name: Install Visual Studio 2022 dependencies
run: |
choco install visualstudio2022-workload-manageddesktop -y
if ($LASTEXITCODE -ne 0) { exit 1 }
choco install visualstudio2022-workload-nativedesktop -y
if ($LASTEXITCODE -ne 0) { exit 1 }
choco install visualstudio2022-workload-vctools -y
if ($LASTEXITCODE -ne 0) { exit 1 }
choco install windowsdriverkit11 -y
if ($LASTEXITCODE -ne 0) { exit 1 }
- name: Build the driver
run: |
msbuild "Virtual Display Driver (HDR)/MTTVDD.sln" /p:Configuration=${{ matrix.configuration }} /p:Platform=${{ matrix.platform }}
- name: List build directory
run: dir "Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD"
- name: Upload built driver
id: upload_artifact
uses: actions/upload-artifact@v4
with:
name: Built-Driver-${{ matrix.configuration }}-${{ matrix.platform }}
path: |
Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD\MttVDD.dll
Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD\MttVDD.inf
Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD\mttvdd.cat
Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD\vdd_settings.xml
- name: Generate release tag
id: generate_tag
run: |
$releaseTag = (Get-Date).ToString('yy.MM.dd')
echo "RELEASE_TAG=$releaseTag" >> $env:GITHUB_ENV
- name: Show generated release tag
run: |
echo "Generated Release Tag: ${{ env.RELEASE_TAG }}"
- name: Verify Built Artifacts
run: dir 'Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD'
+6
View File
@@ -240,3 +240,9 @@ ModelManifest.xml
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
**/.claude/settings.local.json
CLAUDE.md
+3
View File
@@ -0,0 +1,3 @@
[submodule "ThirdParty/Windows-Driver-Frameworks"]
path = ThirdParty/Windows-Driver-Frameworks
url = https://github.com/microsoft/Windows-Driver-Frameworks.git
+104 -2
View File
@@ -3,10 +3,26 @@
#include <wrl/client.h> // For ComPtr
#include <dxgi.h> // For IDXGIAdapter, IDXGIFactory1
#include <algorithm> // For sort
#include <setupapi.h>
#include <devguid.h>
#include <devpropdef.h>
#include <devpkey.h>
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
using namespace Microsoft::WRL;
// DEVPKEY_Device_Luid: {60b193cb-5276-4d0f-96fc-f173ab17af69}, 2
// Define it ourselves to avoid SDK/WDK header differences where DEVPKEY_Device_Luid may not be declared.
static const DEVPROPKEY DEVPKEY_Device_Luid_Custom = {
{ 0x60b193cb, 0x5276, 0x4d0f, { 0x96, 0xfc, 0xf1, 0x73, 0xab, 0xad, 0x3e, 0xc6 } },
2
};
// Structure to vector gpus
struct GPUInfo {
wstring name; // GPU name
@@ -49,6 +65,68 @@ vector<GPUInfo> getAvailableGPUs() {
return gpus;
}
// Resolve an adapter LUID from a PCI bus number by enumerating display devices (SetupAPI).
// Returns nullopt if no match is found or if the system doesn't expose the LUID property.
inline std::optional<LUID> ResolveAdapterLuidFromPciBus(uint32_t targetBusIndex) {
HDEVINFO devInfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, nullptr, nullptr, DIGCF_PRESENT);
if (devInfo == INVALID_HANDLE_VALUE) {
return std::nullopt;
}
SP_DEVINFO_DATA devData = {};
devData.cbSize = sizeof(devData);
std::optional<LUID> result = std::nullopt;
for (DWORD i = 0; SetupDiEnumDeviceInfo(devInfo, i, &devData); ++i) {
DWORD currentBus = 0;
if (!SetupDiGetDeviceRegistryPropertyW(
devInfo,
&devData,
SPDRP_BUSNUMBER,
nullptr,
reinterpret_cast<PBYTE>(&currentBus),
sizeof(currentBus),
nullptr)) {
continue;
}
if (static_cast<uint32_t>(currentBus) != targetBusIndex) {
continue;
}
// DEVPKEY_Device_Luid is exposed as a UINT64 on Windows; convert into LUID.
DEVPROPTYPE propType = 0;
ULONG propSize = 0;
ULONGLONG luid64 = 0;
if (!SetupDiGetDevicePropertyW(
devInfo,
&devData,
&DEVPKEY_Device_Luid_Custom,
&propType,
reinterpret_cast<PBYTE>(&luid64),
sizeof(luid64),
&propSize,
0)) {
continue;
}
if (propType != DEVPROP_TYPE_UINT64 || propSize != sizeof(luid64)) {
continue;
}
LUID luid{};
luid.LowPart = static_cast<DWORD>(luid64 & 0xFFFFFFFFull);
luid.HighPart = static_cast<LONG>((luid64 >> 32) & 0xFFFFFFFFull);
result = luid;
break;
}
SetupDiDestroyDeviceInfoList(devInfo);
return result;
}
class AdapterOption {
public:
bool hasTargetAdapter{}; // Indicates if a target adapter is selected
@@ -110,8 +188,32 @@ public:
}
private:
// Find and set the adapter by its name
bool findAndSetAdapter(const wstring& adapterName) {
// Find and set the adapter by name, optionally using "name,bus" where bus is the PCI bus number.
bool findAndSetAdapter(const wstring& adapterSpec) {
// If user provides "name,bus", use bus to resolve LUID (more deterministic on multi-GPU setups).
const size_t comma = adapterSpec.find(L',');
if (comma != wstring::npos) {
const wstring namePart = adapterSpec.substr(0, comma);
wstring busPart = adapterSpec.substr(comma + 1);
// Trim whitespace in bus part
busPart.erase(remove_if(busPart.begin(), busPart.end(), iswspace), busPart.end());
wchar_t* end = nullptr;
const unsigned long busUl = wcstoul(busPart.c_str(), &end, 10);
const bool parsedOk = (end != nullptr) && (*end == L'\0') && (end != busPart.c_str());
if (parsedOk && busUl <= 0xFFFFFFFFul) {
if (auto luidOpt = ResolveAdapterLuidFromPciBus(static_cast<uint32_t>(busUl)); luidOpt.has_value()) {
adapterLuid = luidOpt.value();
hasTargetAdapter = true;
return true;
}
}
// Fall through to name matching using the name portion.
return findAndSetAdapter(namePart);
}
const wstring& adapterName = adapterSpec;
auto gpus = getAvailableGPUs();
// Iterate through all available GPUs
-1
View File
@@ -1 +0,0 @@
Note: Some of the files included with installer files may use code from outside sources and as such, would not be covered by the open source license. Only the virtual display driver itself is fully FOSS, while other terms may apply based on the installer packaging method used.
@@ -1,202 +0,0 @@
# Rules in this file were initially inferred by Visual Studio IntelliCode from the Template Studio codebase.
# You can modify the rules from these initially generated values to suit your own policies.
# You can learn more about editorconfig here: https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference.
[*.cs]
#Core editorconfig formatting - indentation
#use soft tabs (spaces) for indentation
indent_style = space
#Formatting - new line options
#place else statements on a new line
csharp_new_line_before_else = true
#require braces to be on a new line for lambdas, methods, control_blocks, types, properties, and accessors (also known as "Allman" style)
csharp_new_line_before_open_brace = all
#Formatting - organize using options
#sort System.* using directives alphabetically, and place them before other usings
dotnet_sort_system_directives_first = true
#Formatting - spacing options
#require NO space between a cast and the value
csharp_space_after_cast = false
#require a space before the colon for bases or interfaces in a type declaration
csharp_space_after_colon_in_inheritance_clause = true
#require a space after a keyword in a control flow statement such as a for loop
csharp_space_after_keywords_in_control_flow_statements = true
#require a space before the colon for bases or interfaces in a type declaration
csharp_space_before_colon_in_inheritance_clause = true
#remove space within empty argument list parentheses
csharp_space_between_method_call_empty_parameter_list_parentheses = false
#remove space between method call name and opening parenthesis
csharp_space_between_method_call_name_and_opening_parenthesis = false
#do not place space characters after the opening parenthesis and before the closing parenthesis of a method call
csharp_space_between_method_call_parameter_list_parentheses = false
#remove space within empty parameter list parentheses for a method declaration
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
#place a space character after the opening parenthesis and before the closing parenthesis of a method declaration parameter list.
csharp_space_between_method_declaration_parameter_list_parentheses = false
#Formatting - wrapping options
#leave code block on separate lines
csharp_preserve_single_line_blocks = false
#Style - Code block preferences
#prefer curly braces even for one line of code
csharp_prefer_braces = true:suggestion
#Style - expression bodied member options
#prefer expression bodies for accessors
csharp_style_expression_bodied_accessors = true:warning
#prefer block bodies for constructors
csharp_style_expression_bodied_constructors = false:suggestion
#prefer expression bodies for methods
csharp_style_expression_bodied_methods = when_on_single_line:silent
#prefer expression-bodied members for properties
csharp_style_expression_bodied_properties = true:warning
#Style - expression level options
#prefer out variables to be declared before the method call
csharp_style_inlined_variable_declaration = false:suggestion
#prefer the language keyword for member access expressions, instead of the type name, for types that have a keyword to represent them
dotnet_style_predefined_type_for_member_access = true:suggestion
#Style - Expression-level preferences
#prefer default over default(T)
csharp_prefer_simple_default_expression = true:suggestion
#prefer objects to be initialized using object initializers when possible
dotnet_style_object_initializer = true:suggestion
#Style - implicit and explicit types
#prefer var over explicit type in all cases, unless overridden by another code style rule
csharp_style_var_elsewhere = true:suggestion
#prefer var is used to declare variables with built-in system types such as int
csharp_style_var_for_built_in_types = true:suggestion
#prefer var when the type is already mentioned on the right-hand side of a declaration expression
csharp_style_var_when_type_is_apparent = true:suggestion
#Style - language keyword and framework type options
#prefer the language keyword for local variables, method parameters, and class members, instead of the type name, for types that have a keyword to represent them
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
#Style - Language rules
csharp_style_implicit_object_creation_when_type_is_apparent = true:warning
csharp_style_var_for_built_in_types = true:warning
#Style - modifier options
#prefer accessibility modifiers to be declared except for public interface members. This will currently not differ from always and will act as future proofing for if C# adds default interface methods.
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
#Style - Modifier preferences
#when this rule is set to a list of modifiers, prefer the specified ordering.
csharp_preferred_modifier_order = public,private,protected,internal,static,async,readonly,override,sealed,abstract,virtual:warning
dotnet_style_readonly_field = true:warning
#Style - Pattern matching
#prefer pattern matching instead of is expression with type casts
csharp_style_pattern_matching_over_as_with_null_check = true:warning
#Style - qualification options
#prefer events not to be prefaced with this. or Me. in Visual Basic
dotnet_style_qualification_for_event = false:suggestion
#prefer fields not to be prefaced with this. or Me. in Visual Basic
dotnet_style_qualification_for_field = false:suggestion
#prefer methods not to be prefaced with this. or Me. in Visual Basic
dotnet_style_qualification_for_method = false:suggestion
#prefer properties not to be prefaced with this. or Me. in Visual Basic
dotnet_style_qualification_for_property = false:suggestion
csharp_indent_labels = one_less_than_current
csharp_using_directive_placement = outside_namespace:silent
csharp_prefer_simple_using_statement = true:warning
csharp_style_namespace_declarations = file_scoped:warning
csharp_style_expression_bodied_operators = false:silent
csharp_style_expression_bodied_indexers = true:silent
csharp_style_expression_bodied_lambdas = true:silent
csharp_style_expression_bodied_local_functions = false:silent
[*.{cs,vb}]
dotnet_style_operator_placement_when_wrapping = beginning_of_line
tab_width = 4
indent_size = 4
end_of_line = crlf
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
dotnet_style_prefer_auto_properties = true:silent
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
dotnet_style_prefer_conditional_expression_over_return = true:silent
[*.{cs,vb}]
#Style - Unnecessary code rules
csharp_style_unused_value_assignment_preference = discard_variable:warning
#### Naming styles ####
# Naming rules
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
# Symbol specifications
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.types.required_modifiers =
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.non_field_members.required_modifiers =
# Naming styles
dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.begins_with_i.capitalization = pascal_case
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_compound_assignment = true:warning
dotnet_style_prefer_simplified_interpolation = true:suggestion
-16
View File
@@ -1,16 +0,0 @@
{
"version": "1.0",
"components": [
"Microsoft.Component.MSBuild",
"Microsoft.NetCore.Component.Runtime.7.0",
"Microsoft.NetCore.Component.SDK",
"Microsoft.VisualStudio.Component.ManagedDesktop.Core",
"Microsoft.VisualStudio.Component.ManagedDesktop.Prerequisites",
"Microsoft.VisualStudio.Component.NuGet",
"Microsoft.VisualStudio.Component.Windows10SDK.19041",
"Microsoft.VisualStudio.Component.Windows10SDK",
"Microsoft.VisualStudio.ComponentGroup.MSIX.Packaging",
"Microsoft.VisualStudio.ComponentGroup.WindowsAppSDK.Cs",
"Microsoft.VisualStudio.Workload.ManagedDesktop"
]
}
@@ -1,10 +0,0 @@
namespace VDD_Panel.Core.Contracts.Services;
public interface IFileService
{
T Read<T>(string folderPath, string fileName);
void Save<T>(string folderPath, string fileName, T content);
void Delete(string folderPath, string fileName);
}
@@ -1,22 +0,0 @@
using Newtonsoft.Json;
namespace VDD_Panel.Core.Helpers;
public static class Json
{
public static async Task<T> ToObjectAsync<T>(string value)
{
return await Task.Run<T>(() =>
{
return JsonConvert.DeserializeObject<T>(value);
});
}
public static async Task<string> StringifyAsync(object value)
{
return await Task.Run<string>(() =>
{
return JsonConvert.SerializeObject(value);
});
}
}
@@ -1,5 +0,0 @@
*Recommended Markdown Viewer: [Markdown Editor](https://marketplace.visualstudio.com/items?itemName=MadsKristensen.MarkdownEditor2)*
## Getting Started
The Core project contains code that can be [reused across multiple application projects](https://docs.microsoft.com/dotnet/standard/net-standard#net-5-and-net-standard).
@@ -1,41 +0,0 @@
using System.Text;
using Newtonsoft.Json;
using VDD_Panel.Core.Contracts.Services;
namespace VDD_Panel.Core.Services;
public class FileService : IFileService
{
public T Read<T>(string folderPath, string fileName)
{
var path = Path.Combine(folderPath, fileName);
if (File.Exists(path))
{
var json = File.ReadAllText(path);
return JsonConvert.DeserializeObject<T>(json);
}
return default;
}
public void Save<T>(string folderPath, string fileName, T content)
{
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
}
var fileContent = JsonConvert.SerializeObject(content);
File.WriteAllText(Path.Combine(folderPath, fileName), fileContent, Encoding.UTF8);
}
public void Delete(string folderPath, string fileName)
{
if (fileName != null && File.Exists(Path.Combine(folderPath, fileName)))
{
File.Delete(Path.Combine(folderPath, fileName));
}
}
}
@@ -1,17 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<RootNamespace>VDD_Panel.Core</RootNamespace>
<Platforms>AnyCPU;x64;x86</Platforms>
<Platforms>x86;x64;arm64;AnyCPU</Platforms>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<Folder Include="Models\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup>
</Project>
@@ -1,69 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34622.214
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VDD Panel", "VDD Panel\VDD Panel.csproj", "{5FA23A93-E3D0-46A3-89AA-A909685E2784}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VDD Panel.Core", "VDD Panel.Core\VDD Panel.Core.csproj", "{29E3EAF5-65AE-4ACA-B550-983DBCE38E03}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|arm64 = Debug|arm64
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|arm64 = Release|arm64
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Debug|Any CPU.ActiveCfg = Debug|x64
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Debug|Any CPU.Build.0 = Debug|x64
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Debug|Any CPU.Deploy.0 = Debug|x64
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Debug|arm64.ActiveCfg = Debug|arm64
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Debug|arm64.Build.0 = Debug|arm64
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Debug|arm64.Deploy.0 = Debug|arm64
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Debug|x64.ActiveCfg = Debug|x64
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Debug|x64.Build.0 = Debug|x64
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Debug|x64.Deploy.0 = Debug|x64
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Debug|x86.ActiveCfg = Debug|x86
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Debug|x86.Build.0 = Debug|x86
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Debug|x86.Deploy.0 = Debug|x86
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Release|Any CPU.ActiveCfg = Release|x64
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Release|Any CPU.Build.0 = Release|x64
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Release|Any CPU.Deploy.0 = Release|x64
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Release|arm64.ActiveCfg = Release|arm64
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Release|arm64.Build.0 = Release|arm64
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Release|arm64.Deploy.0 = Release|arm64
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Release|x64.ActiveCfg = Release|x64
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Release|x64.Build.0 = Release|x64
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Release|x64.Deploy.0 = Release|x64
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Release|x86.ActiveCfg = Release|x86
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Release|x86.Build.0 = Release|x86
{5FA23A93-E3D0-46A3-89AA-A909685E2784}.Release|x86.Deploy.0 = Release|x86
{29E3EAF5-65AE-4ACA-B550-983DBCE38E03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{29E3EAF5-65AE-4ACA-B550-983DBCE38E03}.Debug|Any CPU.Build.0 = Debug|Any CPU
{29E3EAF5-65AE-4ACA-B550-983DBCE38E03}.Debug|arm64.ActiveCfg = Debug|arm64
{29E3EAF5-65AE-4ACA-B550-983DBCE38E03}.Debug|arm64.Build.0 = Debug|arm64
{29E3EAF5-65AE-4ACA-B550-983DBCE38E03}.Debug|x64.ActiveCfg = Debug|x64
{29E3EAF5-65AE-4ACA-B550-983DBCE38E03}.Debug|x64.Build.0 = Debug|x64
{29E3EAF5-65AE-4ACA-B550-983DBCE38E03}.Debug|x86.ActiveCfg = Debug|x86
{29E3EAF5-65AE-4ACA-B550-983DBCE38E03}.Debug|x86.Build.0 = Debug|x86
{29E3EAF5-65AE-4ACA-B550-983DBCE38E03}.Release|Any CPU.ActiveCfg = Release|Any CPU
{29E3EAF5-65AE-4ACA-B550-983DBCE38E03}.Release|Any CPU.Build.0 = Release|Any CPU
{29E3EAF5-65AE-4ACA-B550-983DBCE38E03}.Release|arm64.ActiveCfg = Release|arm64
{29E3EAF5-65AE-4ACA-B550-983DBCE38E03}.Release|arm64.Build.0 = Release|arm64
{29E3EAF5-65AE-4ACA-B550-983DBCE38E03}.Release|x64.ActiveCfg = Release|x64
{29E3EAF5-65AE-4ACA-B550-983DBCE38E03}.Release|x64.Build.0 = Release|x64
{29E3EAF5-65AE-4ACA-B550-983DBCE38E03}.Release|x86.ActiveCfg = Release|x86
{29E3EAF5-65AE-4ACA-B550-983DBCE38E03}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {81C98471-4829-40B4-B60F-CEB2472667FC}
EndGlobalSection
EndGlobal
@@ -1,17 +0,0 @@
namespace VDD_Panel.Activation;
// Extend this class to implement new ActivationHandlers. See DefaultActivationHandler for an example.
// https://github.com/microsoft/TemplateStudio/blob/main/docs/WinUI/activation.md
public abstract class ActivationHandler<T> : IActivationHandler
where T : class
{
// Override this method to add the logic for whether to handle the activation.
protected virtual bool CanHandleInternal(T args) => true;
// Override this method to add the logic for your activation handler.
protected abstract Task HandleInternalAsync(T args);
public bool CanHandle(object args) => args is T && CanHandleInternal((args as T)!);
public async Task HandleAsync(object args) => await HandleInternalAsync((args as T)!);
}
@@ -1,51 +0,0 @@
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;
using Microsoft.Windows.AppLifecycle;
using Microsoft.Windows.AppNotifications;
using VDD_Panel.Contracts.Services;
using VDD_Panel.ViewModels;
namespace VDD_Panel.Activation;
public class AppNotificationActivationHandler : ActivationHandler<LaunchActivatedEventArgs>
{
private readonly INavigationService _navigationService;
private readonly IAppNotificationService _notificationService;
public AppNotificationActivationHandler(INavigationService navigationService, IAppNotificationService notificationService)
{
_navigationService = navigationService;
_notificationService = notificationService;
}
protected override bool CanHandleInternal(LaunchActivatedEventArgs args)
{
return AppInstance.GetCurrent().GetActivatedEventArgs()?.Kind == ExtendedActivationKind.AppNotification;
}
protected async override Task HandleInternalAsync(LaunchActivatedEventArgs args)
{
// TODO: Handle notification activations.
//// // Access the AppNotificationActivatedEventArgs.
//// var activatedEventArgs = (AppNotificationActivatedEventArgs)AppInstance.GetCurrent().GetActivatedEventArgs().Data;
//// // Navigate to a specific page based on the notification arguments.
//// if (_notificationService.ParseArguments(activatedEventArgs.Argument)["action"] == "Settings")
//// {
//// // Queue navigation with low priority to allow the UI to initialize.
//// App.MainWindow.DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
//// {
//// _navigationService.NavigateTo(typeof(SettingsViewModel).FullName!);
//// });
//// }
App.MainWindow.DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
{
App.MainWindow.ShowMessageDialogAsync("TODO: Handle notification activations.", "Notification Activation");
});
await Task.CompletedTask;
}
}
@@ -1,29 +0,0 @@
using Microsoft.UI.Xaml;
using VDD_Panel.Contracts.Services;
using VDD_Panel.ViewModels;
namespace VDD_Panel.Activation;
public class DefaultActivationHandler : ActivationHandler<LaunchActivatedEventArgs>
{
private readonly INavigationService _navigationService;
public DefaultActivationHandler(INavigationService navigationService)
{
_navigationService = navigationService;
}
protected override bool CanHandleInternal(LaunchActivatedEventArgs args)
{
// None of the ActivationHandlers has handled the activation.
return _navigationService.Frame?.Content == null;
}
protected async override Task HandleInternalAsync(LaunchActivatedEventArgs args)
{
_navigationService.NavigateTo(typeof(MainViewModel).FullName!, args.Arguments);
await Task.CompletedTask;
}
}
@@ -1,8 +0,0 @@
namespace VDD_Panel.Activation;
public interface IActivationHandler
{
bool CanHandle(object args);
Task HandleAsync(object args);
}
@@ -1,15 +0,0 @@
<Application
x:Class="VDD_Panel.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<ResourceDictionary Source="/Styles/FontSizes.xaml" />
<ResourceDictionary Source="/Styles/Thickness.xaml" />
<ResourceDictionary Source="/Styles/TextBlock.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
@@ -1,111 +0,0 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.UI.Xaml;
using VDD_Panel.Activation;
using VDD_Panel.Contracts.Services;
using VDD_Panel.Core.Contracts.Services;
using VDD_Panel.Core.Services;
using VDD_Panel.Helpers;
using VDD_Panel.Models;
using VDD_Panel.Notifications;
using VDD_Panel.Services;
using VDD_Panel.ViewModels;
using VDD_Panel.Views;
namespace VDD_Panel;
// To learn more about WinUI 3, see https://docs.microsoft.com/windows/apps/winui/winui3/.
public partial class App : Application
{
// The .NET Generic Host provides dependency injection, configuration, logging, and other services.
// https://docs.microsoft.com/dotnet/core/extensions/generic-host
// https://docs.microsoft.com/dotnet/core/extensions/dependency-injection
// https://docs.microsoft.com/dotnet/core/extensions/configuration
// https://docs.microsoft.com/dotnet/core/extensions/logging
public IHost Host
{
get;
}
public static T GetService<T>()
where T : class
{
if ((App.Current as App)!.Host.Services.GetService(typeof(T)) is not T service)
{
throw new ArgumentException($"{typeof(T)} needs to be registered in ConfigureServices within App.xaml.cs.");
}
return service;
}
public static WindowEx MainWindow { get; } = new MainWindow();
public static UIElement? AppTitlebar { get; set; }
public App()
{
InitializeComponent();
Host = Microsoft.Extensions.Hosting.Host.
CreateDefaultBuilder().
UseContentRoot(AppContext.BaseDirectory).
ConfigureServices((context, services) =>
{
// Default Activation Handler
services.AddTransient<ActivationHandler<LaunchActivatedEventArgs>, DefaultActivationHandler>();
// Other Activation Handlers
services.AddTransient<IActivationHandler, AppNotificationActivationHandler>();
// Services
services.AddSingleton<IAppNotificationService, AppNotificationService>();
services.AddSingleton<ILocalSettingsService, LocalSettingsService>();
services.AddSingleton<IThemeSelectorService, ThemeSelectorService>();
services.AddTransient<IWebViewService, WebViewService>();
services.AddTransient<INavigationViewService, NavigationViewService>();
services.AddSingleton<IActivationService, ActivationService>();
services.AddSingleton<IPageService, PageService>();
services.AddSingleton<INavigationService, NavigationService>();
// Core Services
services.AddSingleton<IFileService, FileService>();
// Views and ViewModels
services.AddTransient<SettingsViewModel>();
services.AddTransient<SettingsPage>();
services.AddTransient<GitHubViewModel>();
services.AddTransient<GitHubPage>();
services.AddTransient<ConfigureViewModel>();
services.AddTransient<ConfigurePage>();
services.AddTransient<MainViewModel>();
services.AddTransient<MainPage>();
services.AddTransient<ShellPage>();
services.AddTransient<ShellViewModel>();
// Configuration
services.Configure<LocalSettingsOptions>(context.Configuration.GetSection(nameof(LocalSettingsOptions)));
}).
Build();
App.GetService<IAppNotificationService>().Initialize();
UnhandledException += App_UnhandledException;
}
private void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e)
{
// TODO: Log and handle exceptions as appropriate.
// https://docs.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.application.unhandledexception.
}
protected async override void OnLaunched(LaunchActivatedEventArgs args)
{
base.OnLaunched(args);
App.GetService<IAppNotificationService>().Show(string.Format("AppNotificationSamplePayload".GetLocalized(), AppContext.BaseDirectory));
await App.GetService<IActivationService>().ActivateAsync(args);
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

@@ -1,122 +0,0 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
using Microsoft.Xaml.Interactivity;
using VDD_Panel.Contracts.Services;
namespace VDD_Panel.Behaviors;
public class NavigationViewHeaderBehavior : Behavior<NavigationView>
{
private static NavigationViewHeaderBehavior? _current;
private Page? _currentPage;
public DataTemplate? DefaultHeaderTemplate
{
get; set;
}
public object DefaultHeader
{
get => GetValue(DefaultHeaderProperty);
set => SetValue(DefaultHeaderProperty, value);
}
public static readonly DependencyProperty DefaultHeaderProperty =
DependencyProperty.Register("DefaultHeader", typeof(object), typeof(NavigationViewHeaderBehavior), new PropertyMetadata(null, (d, e) => _current!.UpdateHeader()));
public static NavigationViewHeaderMode GetHeaderMode(Page item) => (NavigationViewHeaderMode)item.GetValue(HeaderModeProperty);
public static void SetHeaderMode(Page item, NavigationViewHeaderMode value) => item.SetValue(HeaderModeProperty, value);
public static readonly DependencyProperty HeaderModeProperty =
DependencyProperty.RegisterAttached("HeaderMode", typeof(bool), typeof(NavigationViewHeaderBehavior), new PropertyMetadata(NavigationViewHeaderMode.Always, (d, e) => _current!.UpdateHeader()));
public static object GetHeaderContext(Page item) => item.GetValue(HeaderContextProperty);
public static void SetHeaderContext(Page item, object value) => item.SetValue(HeaderContextProperty, value);
public static readonly DependencyProperty HeaderContextProperty =
DependencyProperty.RegisterAttached("HeaderContext", typeof(object), typeof(NavigationViewHeaderBehavior), new PropertyMetadata(null, (d, e) => _current!.UpdateHeader()));
public static DataTemplate GetHeaderTemplate(Page item) => (DataTemplate)item.GetValue(HeaderTemplateProperty);
public static void SetHeaderTemplate(Page item, DataTemplate value) => item.SetValue(HeaderTemplateProperty, value);
public static readonly DependencyProperty HeaderTemplateProperty =
DependencyProperty.RegisterAttached("HeaderTemplate", typeof(DataTemplate), typeof(NavigationViewHeaderBehavior), new PropertyMetadata(null, (d, e) => _current!.UpdateHeaderTemplate()));
protected override void OnAttached()
{
base.OnAttached();
var navigationService = App.GetService<INavigationService>();
navigationService.Navigated += OnNavigated;
_current = this;
}
protected override void OnDetaching()
{
base.OnDetaching();
var navigationService = App.GetService<INavigationService>();
navigationService.Navigated -= OnNavigated;
}
private void OnNavigated(object sender, NavigationEventArgs e)
{
if (sender is Frame frame && frame.Content is Page page)
{
_currentPage = page;
UpdateHeader();
UpdateHeaderTemplate();
}
}
private void UpdateHeader()
{
if (_currentPage != null)
{
var headerMode = GetHeaderMode(_currentPage);
if (headerMode == NavigationViewHeaderMode.Never)
{
AssociatedObject.Header = null;
AssociatedObject.AlwaysShowHeader = false;
}
else
{
var headerFromPage = GetHeaderContext(_currentPage);
if (headerFromPage != null)
{
AssociatedObject.Header = headerFromPage;
}
else
{
AssociatedObject.Header = DefaultHeader;
}
if (headerMode == NavigationViewHeaderMode.Always)
{
AssociatedObject.AlwaysShowHeader = true;
}
else
{
AssociatedObject.AlwaysShowHeader = false;
}
}
}
}
private void UpdateHeaderTemplate()
{
if (_currentPage != null)
{
var headerTemplate = GetHeaderTemplate(_currentPage);
AssociatedObject.HeaderTemplate = headerTemplate ?? DefaultHeaderTemplate;
}
}
}
@@ -1,8 +0,0 @@
namespace VDD_Panel.Behaviors;
public enum NavigationViewHeaderMode
{
Always,
Never,
Minimal
}
@@ -1,6 +0,0 @@
namespace VDD_Panel.Contracts.Services;
public interface IActivationService
{
Task ActivateAsync(object activationArgs);
}
@@ -1,14 +0,0 @@
using System.Collections.Specialized;
namespace VDD_Panel.Contracts.Services;
public interface IAppNotificationService
{
void Initialize();
bool Show(string payload);
NameValueCollection ParseArguments(string arguments);
void Unregister();
}
@@ -1,8 +0,0 @@
namespace VDD_Panel.Contracts.Services;
public interface ILocalSettingsService
{
Task<T?> ReadSettingAsync<T>(string key);
Task SaveSettingAsync<T>(string key, T value);
}
@@ -1,23 +0,0 @@
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace VDD_Panel.Contracts.Services;
public interface INavigationService
{
event NavigatedEventHandler Navigated;
bool CanGoBack
{
get;
}
Frame? Frame
{
get; set;
}
bool NavigateTo(string pageKey, object? parameter = null, bool clearNavigation = false);
bool GoBack();
}
@@ -1,22 +0,0 @@
using Microsoft.UI.Xaml.Controls;
namespace VDD_Panel.Contracts.Services;
public interface INavigationViewService
{
IList<object>? MenuItems
{
get;
}
object? SettingsItem
{
get;
}
void Initialize(NavigationView navigationView);
void UnregisterEvents();
NavigationViewItem? GetSelectedItem(Type pageType);
}
@@ -1,6 +0,0 @@
namespace VDD_Panel.Contracts.Services;
public interface IPageService
{
Type GetPageType(string key);
}
@@ -1,17 +0,0 @@
using Microsoft.UI.Xaml;
namespace VDD_Panel.Contracts.Services;
public interface IThemeSelectorService
{
ElementTheme Theme
{
get;
}
Task InitializeAsync();
Task SetThemeAsync(ElementTheme theme);
Task SetRequestedThemeAsync();
}
@@ -1,34 +0,0 @@
using Microsoft.UI.Xaml.Controls;
using Microsoft.Web.WebView2.Core;
namespace VDD_Panel.Contracts.Services;
public interface IWebViewService
{
Uri? Source
{
get;
}
bool CanGoBack
{
get;
}
bool CanGoForward
{
get;
}
event EventHandler<CoreWebView2WebErrorStatus>? NavigationCompleted;
void Initialize(WebView2 webView);
void GoBack();
void GoForward();
void Reload();
void UnregisterEvents();
}
@@ -1,8 +0,0 @@
namespace VDD_Panel.Contracts.ViewModels;
public interface INavigationAware
{
void OnNavigatedTo(object parameter);
void OnNavigatedFrom();
}
@@ -1,38 +0,0 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Data;
namespace VDD_Panel.Helpers;
public class EnumToBooleanConverter : IValueConverter
{
public EnumToBooleanConverter()
{
}
public object Convert(object value, Type targetType, object parameter, string language)
{
if (parameter is string enumString)
{
if (!Enum.IsDefined(typeof(ElementTheme), value))
{
throw new ArgumentException("ExceptionEnumToBooleanConverterValueMustBeAnEnum");
}
var enumValue = Enum.Parse(typeof(ElementTheme), enumString);
return enumValue.Equals(value);
}
throw new ArgumentException("ExceptionEnumToBooleanConverterParameterMustBeAnEnumName");
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
if (parameter is string enumString)
{
return Enum.Parse(typeof(ElementTheme), enumString);
}
throw new ArgumentException("ExceptionEnumToBooleanConverterParameterMustBeAnEnumName");
}
}
@@ -1,8 +0,0 @@
using Microsoft.UI.Xaml.Controls;
namespace VDD_Panel.Helpers;
public static class FrameExtensions
{
public static object? GetPageViewModel(this Frame frame) => frame?.Content?.GetType().GetProperty("ViewModel")?.GetValue(frame.Content, null);
}
@@ -1,21 +0,0 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace VDD_Panel.Helpers;
// Helper class to set the navigation target for a NavigationViewItem.
//
// Usage in XAML:
// <NavigationViewItem x:Uid="Shell_Main" Icon="Document" helpers:NavigationHelper.NavigateTo="AppName.ViewModels.MainViewModel" />
//
// Usage in code:
// NavigationHelper.SetNavigateTo(navigationViewItem, typeof(MainViewModel).FullName);
public class NavigationHelper
{
public static string GetNavigateTo(NavigationViewItem item) => (string)item.GetValue(NavigateToProperty);
public static void SetNavigateTo(NavigationViewItem item, string value) => item.SetValue(NavigateToProperty, value);
public static readonly DependencyProperty NavigateToProperty =
DependencyProperty.RegisterAttached("NavigateTo", typeof(string), typeof(NavigationHelper), new PropertyMetadata(null));
}
@@ -1,10 +0,0 @@
using Microsoft.Windows.ApplicationModel.Resources;
namespace VDD_Panel.Helpers;
public static class ResourceExtensions
{
private static readonly ResourceLoader _resourceLoader = new();
public static string GetLocalized(this string resourceKey) => _resourceLoader.GetString(resourceKey);
}
@@ -1,20 +0,0 @@
using System.Runtime.InteropServices;
using System.Text;
namespace VDD_Panel.Helpers;
public class RuntimeHelper
{
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int GetCurrentPackageFullName(ref int packageFullNameLength, StringBuilder? packageFullName);
public static bool IsMSIX
{
get
{
var length = 0;
return GetCurrentPackageFullName(ref length, null) != 15700L;
}
}
}
@@ -1,112 +0,0 @@
using VDD_Panel.Core.Helpers;
using Windows.Storage;
using Windows.Storage.Streams;
namespace VDD_Panel.Helpers;
// Use these extension methods to store and retrieve local and roaming app data
// More details regarding storing and retrieving app data at https://docs.microsoft.com/windows/apps/design/app-settings/store-and-retrieve-app-data
public static class SettingsStorageExtensions
{
private const string FileExtension = ".json";
public static bool IsRoamingStorageAvailable(this ApplicationData appData)
{
return appData.RoamingStorageQuota == 0;
}
public static async Task SaveAsync<T>(this StorageFolder folder, string name, T content)
{
var file = await folder.CreateFileAsync(GetFileName(name), CreationCollisionOption.ReplaceExisting);
var fileContent = await Json.StringifyAsync(content);
await FileIO.WriteTextAsync(file, fileContent);
}
public static async Task<T?> ReadAsync<T>(this StorageFolder folder, string name)
{
if (!File.Exists(Path.Combine(folder.Path, GetFileName(name))))
{
return default;
}
var file = await folder.GetFileAsync($"{name}.json");
var fileContent = await FileIO.ReadTextAsync(file);
return await Json.ToObjectAsync<T>(fileContent);
}
public static async Task SaveAsync<T>(this ApplicationDataContainer settings, string key, T value)
{
settings.SaveString(key, await Json.StringifyAsync(value));
}
public static void SaveString(this ApplicationDataContainer settings, string key, string value)
{
settings.Values[key] = value;
}
public static async Task<T?> ReadAsync<T>(this ApplicationDataContainer settings, string key)
{
object? obj;
if (settings.Values.TryGetValue(key, out obj))
{
return await Json.ToObjectAsync<T>((string)obj);
}
return default;
}
public static async Task<StorageFile> SaveFileAsync(this StorageFolder folder, byte[] content, string fileName, CreationCollisionOption options = CreationCollisionOption.ReplaceExisting)
{
if (content == null)
{
throw new ArgumentNullException(nameof(content));
}
if (string.IsNullOrEmpty(fileName))
{
throw new ArgumentException("File name is null or empty. Specify a valid file name", nameof(fileName));
}
var storageFile = await folder.CreateFileAsync(fileName, options);
await FileIO.WriteBytesAsync(storageFile, content);
return storageFile;
}
public static async Task<byte[]?> ReadFileAsync(this StorageFolder folder, string fileName)
{
var item = await folder.TryGetItemAsync(fileName).AsTask().ConfigureAwait(false);
if ((item != null) && item.IsOfType(StorageItemTypes.File))
{
var storageFile = await folder.GetFileAsync(fileName);
var content = await storageFile.ReadBytesAsync();
return content;
}
return null;
}
public static async Task<byte[]?> ReadBytesAsync(this StorageFile file)
{
if (file != null)
{
using IRandomAccessStream stream = await file.OpenReadAsync();
using var reader = new DataReader(stream.GetInputStreamAt(0));
await reader.LoadAsync((uint)stream.Size);
var bytes = new byte[stream.Size];
reader.ReadBytes(bytes);
return bytes;
}
return null;
}
private static string GetFileName(string name)
{
return string.Concat(name, FileExtension);
}
}
@@ -1,96 +0,0 @@
using System.Runtime.InteropServices;
using Microsoft.UI;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Media;
using Windows.UI;
using Windows.UI.ViewManagement;
namespace VDD_Panel.Helpers;
// Helper class to workaround custom title bar bugs.
// DISCLAIMER: The resource key names and color values used below are subject to change. Do not depend on them.
// https://github.com/microsoft/TemplateStudio/issues/4516
internal class TitleBarHelper
{
private const int WAINACTIVE = 0x00;
private const int WAACTIVE = 0x01;
private const int WMACTIVATE = 0x0006;
[DllImport("user32.dll")]
private static extern IntPtr GetActiveWindow();
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, IntPtr lParam);
public static void UpdateTitleBar(ElementTheme theme)
{
if (App.MainWindow.ExtendsContentIntoTitleBar)
{
if (theme == ElementTheme.Default)
{
var uiSettings = new UISettings();
var background = uiSettings.GetColorValue(UIColorType.Background);
theme = background == Colors.White ? ElementTheme.Light : ElementTheme.Dark;
}
if (theme == ElementTheme.Default)
{
theme = Application.Current.RequestedTheme == ApplicationTheme.Light ? ElementTheme.Light : ElementTheme.Dark;
}
App.MainWindow.AppWindow.TitleBar.ButtonForegroundColor = theme switch
{
ElementTheme.Dark => Colors.White,
ElementTheme.Light => Colors.Black,
_ => Colors.Transparent
};
App.MainWindow.AppWindow.TitleBar.ButtonHoverForegroundColor = theme switch
{
ElementTheme.Dark => Colors.White,
ElementTheme.Light => Colors.Black,
_ => Colors.Transparent
};
App.MainWindow.AppWindow.TitleBar.ButtonHoverBackgroundColor = theme switch
{
ElementTheme.Dark => Color.FromArgb(0x33, 0xFF, 0xFF, 0xFF),
ElementTheme.Light => Color.FromArgb(0x33, 0x00, 0x00, 0x00),
_ => Colors.Transparent
};
App.MainWindow.AppWindow.TitleBar.ButtonPressedBackgroundColor = theme switch
{
ElementTheme.Dark => Color.FromArgb(0x66, 0xFF, 0xFF, 0xFF),
ElementTheme.Light => Color.FromArgb(0x66, 0x00, 0x00, 0x00),
_ => Colors.Transparent
};
App.MainWindow.AppWindow.TitleBar.BackgroundColor = Colors.Transparent;
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(App.MainWindow);
if (hwnd == GetActiveWindow())
{
SendMessage(hwnd, WMACTIVATE, WAINACTIVE, IntPtr.Zero);
SendMessage(hwnd, WMACTIVATE, WAACTIVE, IntPtr.Zero);
}
else
{
SendMessage(hwnd, WMACTIVATE, WAACTIVE, IntPtr.Zero);
SendMessage(hwnd, WMACTIVATE, WAINACTIVE, IntPtr.Zero);
}
}
}
public static void ApplySystemThemeToCaptionButtons()
{
var frame = App.AppTitlebar as FrameworkElement;
if (frame != null)
{
UpdateTitleBar(frame.ActualTheme);
}
}
}
@@ -1,16 +0,0 @@
<windowex:WindowEx
x:Class="VDD_Panel.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:VDD_Panel"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:windowex="using:WinUIEx"
MinWidth="500"
MinHeight="500"
PersistenceId="MainWindow"
mc:Ignorable="d">
<Window.SystemBackdrop>
<MicaBackdrop/>
</Window.SystemBackdrop>
</windowex:WindowEx>
@@ -1,37 +0,0 @@
using VDD_Panel.Helpers;
using Windows.UI.ViewManagement;
namespace VDD_Panel;
public sealed partial class MainWindow : WindowEx
{
private Microsoft.UI.Dispatching.DispatcherQueue dispatcherQueue;
private UISettings settings;
public MainWindow()
{
InitializeComponent();
AppWindow.SetIcon(Path.Combine(AppContext.BaseDirectory, "Assets/WindowIcon.ico"));
Content = null;
Title = "AppDisplayName".GetLocalized();
// Theme change code picked from https://github.com/microsoft/WinUI-Gallery/pull/1239
dispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread();
settings = new UISettings();
settings.ColorValuesChanged += Settings_ColorValuesChanged; // cannot use FrameworkElement.ActualThemeChanged event
}
// this handles updating the caption button colors correctly when indows system theme is changed
// while the app is open
private void Settings_ColorValuesChanged(UISettings sender, object args)
{
// This calls comes off-thread, hence we will need to dispatch it to current app's thread
dispatcherQueue.TryEnqueue(() =>
{
TitleBarHelper.ApplySystemThemeToCaptionButtons();
});
}
}
@@ -1,14 +0,0 @@
namespace VDD_Panel.Models;
public class LocalSettingsOptions
{
public string? ApplicationDataFolder
{
get; set;
}
public string? LocalSettingsFile
{
get; set;
}
}
@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<AppInstaller Uri="{AppInstallerUri}"
Version="{Version}"
xmlns="http://schemas.microsoft.com/appx/appinstaller/2017/2">
<!-- Read more about updating settings with Package.appinstaller at https://docs.microsoft.com/windows/msix/app-installer/update-settings -->
<MainBundle Name="{Name}"
Version="{Version}"
Publisher="{Publisher}"
Uri="{MainPackageUri}"/>
<UpdateSettings>
<OnLaunch HoursBetweenUpdateChecks="0" />
</UpdateSettings>
</AppInstaller>
@@ -1,76 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
xmlns:genTemplate="http://schemas.microsoft.com/appx/developer/templatestudio"
xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
IgnorableNamespaces="uap rescap genTemplate">
<Identity
Name="a7aa779e-510d-4d11-aad6-4cb00d23c8a5"
Publisher="CN=alisa"
Version="1.0.0.0" />
<mp:PhoneIdentity PhoneProductId="a7aa779e-510d-4d11-aad6-4cb00d23c8a5" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
<Properties>
<DisplayName>VDD Panel</DisplayName>
<PublisherDisplayName>alisa</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="$targetentrypoint$">
<uap:VisualElements
DisplayName="ms-resource:AppDisplayName"
Description="ms-resource:AppDescription"
BackgroundColor="transparent"
Square150x150Logo="Assets\Square150x150Logo.png"
Square44x44Logo="Assets\Square44x44Logo.png">
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" />
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
<Extensions>
<desktop:Extension Category="windows.toastNotificationActivation">
<desktop:ToastNotificationActivation ToastActivatorCLSID="17b96de3-608c-4471-85f1-1e9db4531575" />
</desktop:Extension>
<com:Extension Category="windows.comServer">
<com:ComServer>
<com:ExeServer Executable="VDD Panel.exe" Arguments="----AppNotificationActivated:" DisplayName="Toast activator">
<com:Class Id="17b96de3-608c-4471-85f1-1e9db4531575" DisplayName="Toast activator"/>
</com:ExeServer>
</com:ComServer>
</com:Extension>
</Extensions>
</Application>
</Applications>
<Capabilities>
<rescap:Capability Name="runFullTrust" />
</Capabilities>
<genTemplate:Metadata>
<genTemplate:Item Name="generator" Value="Template Studio"/>
<genTemplate:Item Name="wizardVersion" Version="v5.5" />
<genTemplate:Item Name="projectType" Value="NavView" />
<genTemplate:Item Name="framework" Value="MVVMToolkit" />
<genTemplate:Item Name="platform" Value="WinUI" />
<genTemplate:Item Name="appmodel" Value="Desktop" />
</genTemplate:Metadata>
</Package>
@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PublishProtocol>FileSystem</PublishProtocol>
<Platform>arm64</Platform>
<RuntimeIdentifier>win10-arm64</RuntimeIdentifier>
<PublishDir>bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\</PublishDir>
<SelfContained>True</SelfContained>
<PublishSingleFile>False</PublishSingleFile>
<PublishReadyToRun Condition="'$(Configuration)' == 'Debug'">False</PublishReadyToRun>
<PublishReadyToRun Condition="'$(Configuration)' != 'Debug'">True</PublishReadyToRun>
</PropertyGroup>
</Project>
@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PublishProtocol>FileSystem</PublishProtocol>
<Platform>x64</Platform>
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
<PublishDir>bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\</PublishDir>
<SelfContained>True</SelfContained>
<PublishSingleFile>False</PublishSingleFile>
<PublishReadyToRun Condition="'$(Configuration)' == 'Debug'">False</PublishReadyToRun>
<PublishReadyToRun Condition="'$(Configuration)' != 'Debug'">True</PublishReadyToRun>
</PropertyGroup>
</Project>
@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PublishProtocol>FileSystem</PublishProtocol>
<Platform>x86</Platform>
<RuntimeIdentifier>win10-x86</RuntimeIdentifier>
<PublishDir>bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\</PublishDir>
<SelfContained>True</SelfContained>
<PublishSingleFile>False</PublishSingleFile>
<PublishReadyToRun Condition="'$(Configuration)' == 'Debug'">False</PublishReadyToRun>
<PublishReadyToRun Condition="'$(Configuration)' != 'Debug'">True</PublishReadyToRun>
</PropertyGroup>
</Project>
@@ -1,10 +0,0 @@
{
"profiles": {
"VDD Panel (Package)": {
"commandName": "MsixPackage"
},
"VDD Panel (Unpackaged)": {
"commandName": "Project"
}
}
}
@@ -1,27 +0,0 @@
*Recommended Markdown Viewer: [Markdown Editor](https://marketplace.visualstudio.com/items?itemName=MadsKristensen.MarkdownEditor2)*
## Getting Started
Browse and address `TODO:` comments in `View -> Task List` to learn the codebase and understand next steps for turning the generated code into production code.
Explore the [WinUI Gallery](https://www.microsoft.com/store/productId/9P3JFPWWDZRC) to learn about available controls and design patterns.
Relaunch Template Studio to modify the project by right-clicking on the project in `View -> Solution Explorer` then selecting `Add -> New Item (Template Studio)`.
## Publishing
For projects with MSIX packaging, right-click on the application project and select `Package and Publish -> Create App Packages...` to create an MSIX package.
For projects without MSIX packaging, follow the [deployment guide](https://docs.microsoft.com/windows/apps/windows-app-sdk/deploy-unpackaged-apps) or add the `Self-Contained` Feature to enable xcopy deployment.
## CI Pipelines
See [README.md](https://github.com/microsoft/TemplateStudio/blob/main/docs/WinUI/pipelines/README.md) for guidance on building and testing projects in CI pipelines.
## Changelog
See [releases](https://github.com/microsoft/TemplateStudio/releases) and [milestones](https://github.com/microsoft/TemplateStudio/milestones).
## Feedback
Bugs and feature requests should be filed at https://aka.ms/templatestudio.
@@ -1,72 +0,0 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using VDD_Panel.Activation;
using VDD_Panel.Contracts.Services;
using VDD_Panel.Views;
namespace VDD_Panel.Services;
public class ActivationService : IActivationService
{
private readonly ActivationHandler<LaunchActivatedEventArgs> _defaultHandler;
private readonly IEnumerable<IActivationHandler> _activationHandlers;
private readonly IThemeSelectorService _themeSelectorService;
private UIElement? _shell = null;
public ActivationService(ActivationHandler<LaunchActivatedEventArgs> defaultHandler, IEnumerable<IActivationHandler> activationHandlers, IThemeSelectorService themeSelectorService)
{
_defaultHandler = defaultHandler;
_activationHandlers = activationHandlers;
_themeSelectorService = themeSelectorService;
}
public async Task ActivateAsync(object activationArgs)
{
// Execute tasks before activation.
await InitializeAsync();
// Set the MainWindow Content.
if (App.MainWindow.Content == null)
{
_shell = App.GetService<ShellPage>();
App.MainWindow.Content = _shell ?? new Frame();
}
// Handle activation via ActivationHandlers.
await HandleActivationAsync(activationArgs);
// Activate the MainWindow.
App.MainWindow.Activate();
// Execute tasks after activation.
await StartupAsync();
}
private async Task HandleActivationAsync(object activationArgs)
{
var activationHandler = _activationHandlers.FirstOrDefault(h => h.CanHandle(activationArgs));
if (activationHandler != null)
{
await activationHandler.HandleAsync(activationArgs);
}
if (_defaultHandler.CanHandle(activationArgs))
{
await _defaultHandler.HandleAsync(activationArgs);
}
}
private async Task InitializeAsync()
{
await _themeSelectorService.InitializeAsync().ConfigureAwait(false);
await Task.CompletedTask;
}
private async Task StartupAsync()
{
await _themeSelectorService.SetRequestedThemeAsync();
await Task.CompletedTask;
}
}
@@ -1,71 +0,0 @@
using System.Collections.Specialized;
using System.Web;
using Microsoft.Windows.AppNotifications;
using VDD_Panel.Contracts.Services;
using VDD_Panel.ViewModels;
namespace VDD_Panel.Notifications;
public class AppNotificationService : IAppNotificationService
{
private readonly INavigationService _navigationService;
public AppNotificationService(INavigationService navigationService)
{
_navigationService = navigationService;
}
~AppNotificationService()
{
Unregister();
}
public void Initialize()
{
AppNotificationManager.Default.NotificationInvoked += OnNotificationInvoked;
AppNotificationManager.Default.Register();
}
public void OnNotificationInvoked(AppNotificationManager sender, AppNotificationActivatedEventArgs args)
{
// TODO: Handle notification invocations when your app is already running.
//// // Navigate to a specific page based on the notification arguments.
//// if (ParseArguments(args.Argument)["action"] == "Settings")
//// {
//// App.MainWindow.DispatcherQueue.TryEnqueue(() =>
//// {
//// _navigationService.NavigateTo(typeof(SettingsViewModel).FullName!);
//// });
//// }
App.MainWindow.DispatcherQueue.TryEnqueue(() =>
{
App.MainWindow.ShowMessageDialogAsync("TODO: Handle notification invocations when your app is already running.", "Notification Invoked");
App.MainWindow.BringToFront();
});
}
public bool Show(string payload)
{
var appNotification = new AppNotification(payload);
AppNotificationManager.Default.Show(appNotification);
return appNotification.Id != 0;
}
public NameValueCollection ParseArguments(string arguments)
{
return HttpUtility.ParseQueryString(arguments);
}
public void Unregister()
{
AppNotificationManager.Default.Unregister();
}
}
@@ -1,88 +0,0 @@
using Microsoft.Extensions.Options;
using VDD_Panel.Contracts.Services;
using VDD_Panel.Core.Contracts.Services;
using VDD_Panel.Core.Helpers;
using VDD_Panel.Helpers;
using VDD_Panel.Models;
using Windows.ApplicationModel;
using Windows.Storage;
namespace VDD_Panel.Services;
public class LocalSettingsService : ILocalSettingsService
{
private const string _defaultApplicationDataFolder = "VDD Panel/ApplicationData";
private const string _defaultLocalSettingsFile = "LocalSettings.json";
private readonly IFileService _fileService;
private readonly LocalSettingsOptions _options;
private readonly string _localApplicationData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
private readonly string _applicationDataFolder;
private readonly string _localsettingsFile;
private IDictionary<string, object> _settings;
private bool _isInitialized;
public LocalSettingsService(IFileService fileService, IOptions<LocalSettingsOptions> options)
{
_fileService = fileService;
_options = options.Value;
_applicationDataFolder = Path.Combine(_localApplicationData, _options.ApplicationDataFolder ?? _defaultApplicationDataFolder);
_localsettingsFile = _options.LocalSettingsFile ?? _defaultLocalSettingsFile;
_settings = new Dictionary<string, object>();
}
private async Task InitializeAsync()
{
if (!_isInitialized)
{
_settings = await Task.Run(() => _fileService.Read<IDictionary<string, object>>(_applicationDataFolder, _localsettingsFile)) ?? new Dictionary<string, object>();
_isInitialized = true;
}
}
public async Task<T?> ReadSettingAsync<T>(string key)
{
if (RuntimeHelper.IsMSIX)
{
if (ApplicationData.Current.LocalSettings.Values.TryGetValue(key, out var obj))
{
return await Json.ToObjectAsync<T>((string)obj);
}
}
else
{
await InitializeAsync();
if (_settings != null && _settings.TryGetValue(key, out var obj))
{
return await Json.ToObjectAsync<T>((string)obj);
}
}
return default;
}
public async Task SaveSettingAsync<T>(string key, T value)
{
if (RuntimeHelper.IsMSIX)
{
ApplicationData.Current.LocalSettings.Values[key] = await Json.StringifyAsync(value);
}
else
{
await InitializeAsync();
_settings[key] = await Json.StringifyAsync(value);
await Task.Run(() => _fileService.Save(_applicationDataFolder, _localsettingsFile, _settings));
}
}
}
@@ -1,126 +0,0 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
using VDD_Panel.Contracts.Services;
using VDD_Panel.Contracts.ViewModels;
using VDD_Panel.Helpers;
namespace VDD_Panel.Services;
// For more information on navigation between pages see
// https://github.com/microsoft/TemplateStudio/blob/main/docs/WinUI/navigation.md
public class NavigationService : INavigationService
{
private readonly IPageService _pageService;
private object? _lastParameterUsed;
private Frame? _frame;
public event NavigatedEventHandler? Navigated;
public Frame? Frame
{
get
{
if (_frame == null)
{
_frame = App.MainWindow.Content as Frame;
RegisterFrameEvents();
}
return _frame;
}
set
{
UnregisterFrameEvents();
_frame = value;
RegisterFrameEvents();
}
}
[MemberNotNullWhen(true, nameof(Frame), nameof(_frame))]
public bool CanGoBack => Frame != null && Frame.CanGoBack;
public NavigationService(IPageService pageService)
{
_pageService = pageService;
}
private void RegisterFrameEvents()
{
if (_frame != null)
{
_frame.Navigated += OnNavigated;
}
}
private void UnregisterFrameEvents()
{
if (_frame != null)
{
_frame.Navigated -= OnNavigated;
}
}
public bool GoBack()
{
if (CanGoBack)
{
var vmBeforeNavigation = _frame.GetPageViewModel();
_frame.GoBack();
if (vmBeforeNavigation is INavigationAware navigationAware)
{
navigationAware.OnNavigatedFrom();
}
return true;
}
return false;
}
public bool NavigateTo(string pageKey, object? parameter = null, bool clearNavigation = false)
{
var pageType = _pageService.GetPageType(pageKey);
if (_frame != null && (_frame.Content?.GetType() != pageType || (parameter != null && !parameter.Equals(_lastParameterUsed))))
{
_frame.Tag = clearNavigation;
var vmBeforeNavigation = _frame.GetPageViewModel();
var navigated = _frame.Navigate(pageType, parameter);
if (navigated)
{
_lastParameterUsed = parameter;
if (vmBeforeNavigation is INavigationAware navigationAware)
{
navigationAware.OnNavigatedFrom();
}
}
return navigated;
}
return false;
}
private void OnNavigated(object sender, NavigationEventArgs e)
{
if (sender is Frame frame)
{
var clearNavigation = (bool)frame.Tag;
if (clearNavigation)
{
frame.BackStack.Clear();
}
if (frame.GetPageViewModel() is INavigationAware navigationAware)
{
navigationAware.OnNavigatedTo(e.Parameter);
}
Navigated?.Invoke(sender, e);
}
}
}
@@ -1,103 +0,0 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.UI.Xaml.Controls;
using VDD_Panel.Contracts.Services;
using VDD_Panel.Helpers;
using VDD_Panel.ViewModels;
namespace VDD_Panel.Services;
public class NavigationViewService : INavigationViewService
{
private readonly INavigationService _navigationService;
private readonly IPageService _pageService;
private NavigationView? _navigationView;
public IList<object>? MenuItems => _navigationView?.MenuItems;
public object? SettingsItem => _navigationView?.SettingsItem;
public NavigationViewService(INavigationService navigationService, IPageService pageService)
{
_navigationService = navigationService;
_pageService = pageService;
}
[MemberNotNull(nameof(_navigationView))]
public void Initialize(NavigationView navigationView)
{
_navigationView = navigationView;
_navigationView.BackRequested += OnBackRequested;
_navigationView.ItemInvoked += OnItemInvoked;
}
public void UnregisterEvents()
{
if (_navigationView != null)
{
_navigationView.BackRequested -= OnBackRequested;
_navigationView.ItemInvoked -= OnItemInvoked;
}
}
public NavigationViewItem? GetSelectedItem(Type pageType)
{
if (_navigationView != null)
{
return GetSelectedItem(_navigationView.MenuItems, pageType) ?? GetSelectedItem(_navigationView.FooterMenuItems, pageType);
}
return null;
}
private void OnBackRequested(NavigationView sender, NavigationViewBackRequestedEventArgs args) => _navigationService.GoBack();
private void OnItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)
{
if (args.IsSettingsInvoked)
{
_navigationService.NavigateTo(typeof(SettingsViewModel).FullName!);
}
else
{
var selectedItem = args.InvokedItemContainer as NavigationViewItem;
if (selectedItem?.GetValue(NavigationHelper.NavigateToProperty) is string pageKey)
{
_navigationService.NavigateTo(pageKey);
}
}
}
private NavigationViewItem? GetSelectedItem(IEnumerable<object> menuItems, Type pageType)
{
foreach (var item in menuItems.OfType<NavigationViewItem>())
{
if (IsMenuItemForPageType(item, pageType))
{
return item;
}
var selectedChild = GetSelectedItem(item.MenuItems, pageType);
if (selectedChild != null)
{
return selectedChild;
}
}
return null;
}
private bool IsMenuItemForPageType(NavigationViewItem menuItem, Type sourcePageType)
{
if (menuItem.GetValue(NavigationHelper.NavigateToProperty) is string pageKey)
{
return _pageService.GetPageType(pageKey) == sourcePageType;
}
return false;
}
}
@@ -1,58 +0,0 @@
using CommunityToolkit.Mvvm.ComponentModel;
using Microsoft.UI.Xaml.Controls;
using VDD_Panel.Contracts.Services;
using VDD_Panel.ViewModels;
using VDD_Panel.Views;
namespace VDD_Panel.Services;
public class PageService : IPageService
{
private readonly Dictionary<string, Type> _pages = new();
public PageService()
{
Configure<MainViewModel, MainPage>();
Configure<ConfigureViewModel, ConfigurePage>();
Configure<GitHubViewModel, GitHubPage>();
Configure<SettingsViewModel, SettingsPage>();
}
public Type GetPageType(string key)
{
Type? pageType;
lock (_pages)
{
if (!_pages.TryGetValue(key, out pageType))
{
throw new ArgumentException($"Page not found: {key}. Did you forget to call PageService.Configure?");
}
}
return pageType;
}
private void Configure<VM, V>()
where VM : ObservableObject
where V : Page
{
lock (_pages)
{
var key = typeof(VM).FullName!;
if (_pages.ContainsKey(key))
{
throw new ArgumentException($"The key {key} is already configured in PageService");
}
var type = typeof(V);
if (_pages.ContainsValue(type))
{
throw new ArgumentException($"This type is already configured with key {_pages.First(p => p.Value == type).Key}");
}
_pages.Add(key, type);
}
}
}
@@ -1,63 +0,0 @@
using Microsoft.UI.Xaml;
using VDD_Panel.Contracts.Services;
using VDD_Panel.Helpers;
namespace VDD_Panel.Services;
public class ThemeSelectorService : IThemeSelectorService
{
private const string SettingsKey = "AppBackgroundRequestedTheme";
public ElementTheme Theme { get; set; } = ElementTheme.Default;
private readonly ILocalSettingsService _localSettingsService;
public ThemeSelectorService(ILocalSettingsService localSettingsService)
{
_localSettingsService = localSettingsService;
}
public async Task InitializeAsync()
{
Theme = await LoadThemeFromSettingsAsync();
await Task.CompletedTask;
}
public async Task SetThemeAsync(ElementTheme theme)
{
Theme = theme;
await SetRequestedThemeAsync();
await SaveThemeInSettingsAsync(Theme);
}
public async Task SetRequestedThemeAsync()
{
if (App.MainWindow.Content is FrameworkElement rootElement)
{
rootElement.RequestedTheme = Theme;
TitleBarHelper.UpdateTitleBar(Theme);
}
await Task.CompletedTask;
}
private async Task<ElementTheme> LoadThemeFromSettingsAsync()
{
var themeName = await _localSettingsService.ReadSettingAsync<string>(SettingsKey);
if (Enum.TryParse(themeName, out ElementTheme cacheTheme))
{
return cacheTheme;
}
return ElementTheme.Default;
}
private async Task SaveThemeInSettingsAsync(ElementTheme theme)
{
await _localSettingsService.SaveSettingAsync(SettingsKey, theme.ToString());
}
}
@@ -1,50 +0,0 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.UI.Xaml.Controls;
using Microsoft.Web.WebView2.Core;
using VDD_Panel.Contracts.Services;
namespace VDD_Panel.Services;
public class WebViewService : IWebViewService
{
private WebView2? _webView;
public Uri? Source => _webView?.Source;
[MemberNotNullWhen(true, nameof(_webView))]
public bool CanGoBack => _webView != null && _webView.CanGoBack;
[MemberNotNullWhen(true, nameof(_webView))]
public bool CanGoForward => _webView != null && _webView.CanGoForward;
public event EventHandler<CoreWebView2WebErrorStatus>? NavigationCompleted;
public WebViewService()
{
}
[MemberNotNull(nameof(_webView))]
public void Initialize(WebView2 webView)
{
_webView = webView;
_webView.NavigationCompleted += OnWebViewNavigationCompleted;
}
public void GoBack() => _webView?.GoBack();
public void GoForward() => _webView?.GoForward();
public void Reload() => _webView?.Reload();
public void UnregisterEvents()
{
if (_webView != null)
{
_webView.NavigationCompleted -= OnWebViewNavigationCompleted;
}
}
private void OnWebViewNavigationCompleted(WebView2 sender, CoreWebView2NavigationCompletedEventArgs args) => NavigationCompleted?.Invoke(this, args.WebErrorStatus);
}
@@ -1,150 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AppDisplayName" xml:space="preserve">
<value>VDD Panel</value>
</data>
<data name="AppDescription" xml:space="preserve">
<value>VDD Panel</value>
</data>
<data name="Shell_Main.Content" xml:space="preserve">
<value>Main</value>
</data>
<data name="Shell_Configure.Content" xml:space="preserve">
<value>Configure</value>
</data>
<data name="WebView_Loading.Text" xml:space="preserve">
<value>Loading...</value>
</data>
<data name="WebView_FailedMessage.Text" xml:space="preserve">
<value>Page failed to load. Check connection and reload.</value>
</data>
<data name="BrowserBackButton.[using:Microsoft.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Browser back</value>
</data>
<data name="BrowserBackButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Browser back</value>
</data>
<data name="BrowserForwardButton.[using:Microsoft.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Browser forward</value>
</data>
<data name="BrowserForwardButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Browser forward</value>
</data>
<data name="WebView_Reload.Content" xml:space="preserve">
<value>Reload</value>
</data>
<data name="ReloadButton.[using:Microsoft.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Reload</value>
</data>
<data name="ReloadButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Reload</value>
</data>
<data name="OpenInBrowserButton.[using:Microsoft.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Open in browser</value>
</data>
<data name="OpenInBrowserButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Open in browser</value>
</data>
<data name="Shell_GitHub.Content" xml:space="preserve">
<value>GitHub</value>
</data>
<data name="Settings_Personalization.Text" xml:space="preserve">
<value>Personalization</value>
</data>
<data name="Settings_Theme.Text" xml:space="preserve">
<value>Theme</value>
</data>
<data name="Settings_Theme_Light.Content" xml:space="preserve">
<value>Light</value>
</data>
<data name="Settings_Theme_Dark.Content" xml:space="preserve">
<value>Dark</value>
</data>
<data name="Settings_Theme_Default.Content" xml:space="preserve">
<value>Default</value>
</data>
<data name="Settings_About.Text" xml:space="preserve">
<value>About this application</value>
</data>
<data name="Settings_AboutDescription.Text" xml:space="preserve">
<value>TODO: Replace with your app description.</value>
</data>
<data name="SettingsPage_PrivacyTermsLink.Content" xml:space="preserve">
<value>Privacy Statement</value>
</data>
<data name="SettingsPage_PrivacyTermsLink.NavigateUri" xml:space="preserve">
<value>https://YourPrivacyUrlGoesHere/</value>
</data>
<data name="AppNotificationSamplePayload" xml:space="preserve">
<value>&lt;toast launch="action=ToastClick"&gt;
&lt;visual&gt;
&lt;binding template="ToastGeneric"&gt;
&lt;text&gt;App Notification&lt;/text&gt;
&lt;text&gt;&lt;/text&gt;
&lt;image placement="appLogoOverride" hint-crop="circle" src="{0}Assets/WindowIcon.ico"/&gt;
&lt;/binding&gt;
&lt;/visual&gt;
&lt;actions&gt;
&lt;action content="Settings" arguments="action=Settings"/&gt;
&lt;/actions&gt;
&lt;/toast&gt;</value>
</data>
</root>
@@ -1,9 +0,0 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<x:Double x:Key="LargeFontSize">24</x:Double>
<x:Double x:Key="MediumFontSize">16</x:Double>
</ResourceDictionary>
@@ -1,20 +0,0 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="PageTitleStyle" TargetType="TextBlock">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="FontWeight" Value="SemiLight" />
<Setter Property="FontSize" Value="{StaticResource LargeFontSize}" />
<Setter Property="TextTrimming" Value="CharacterEllipsis" />
<Setter Property="TextWrapping" Value="NoWrap" />
</Style>
<Style x:Key="BodyTextStyle" TargetType="TextBlock">
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="FontSize" Value="{StaticResource MediumFontSize}" />
<Setter Property="TextTrimming" Value="CharacterEllipsis" />
<Setter Property="TextWrapping" Value="Wrap" />
</Style>
</ResourceDictionary>
@@ -1,36 +0,0 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Thickness x:Key="LargeTopMargin">0,36,0,0</Thickness>
<Thickness x:Key="LargeTopBottomMargin">0,36,0,36</Thickness>
<Thickness x:Key="MediumTopMargin">0,24,0,0</Thickness>
<Thickness x:Key="MediumTopBottomMargin">0,24,0,24</Thickness>
<Thickness x:Key="MediumLeftRightMargin">24,0,24,0</Thickness>
<Thickness x:Key="MediumBottomMargin">0,0,0,24</Thickness>
<Thickness x:Key="SmallLeftMargin">12,0,0,0</Thickness>
<Thickness x:Key="SmallLeftRightMargin">12,0,12,0</Thickness>
<Thickness x:Key="SmallTopMargin">0,12,0,0</Thickness>
<Thickness x:Key="SmallRightMargin">0,0,12,0</Thickness>
<Thickness x:Key="SmallTopBottomMargin">0,12,0,12</Thickness>
<Thickness x:Key="XSmallLeftMargin">8,0,0,0</Thickness>
<Thickness x:Key="XSmallTopMargin">0,8,0,0</Thickness>
<Thickness x:Key="XSmallLeftTopRightBottomMargin">8,8,8,8</Thickness>
<Thickness x:Key="XXSmallTopMargin">0,4,0,0</Thickness>
<Thickness x:Key="XXSmallLeftTopRightBottomMargin">4,4,4,4</Thickness>
<Thickness x:Key="NavigationViewContentGridBorderThickness">1,1,0,0</Thickness>
<CornerRadius x:Key="NavigationViewContentGridCornerRadius">8,0,0,0</CornerRadius>
<Thickness x:Key="NavigationViewContentMargin">0,48,0,0</Thickness>
<Thickness x:Key="NavigationViewHeaderMargin">56,34,0,0</Thickness>
<Thickness x:Key="NavigationViewPageContentMargin">56,24,56,0</Thickness>
<Thickness x:Key="MenuBarContentMargin">36,24,36,0</Thickness>
<Thickness x:Key="SettingsPageHyperlinkButtonMargin">-12,4,0,0</Thickness>
</ResourceDictionary>
@@ -1,11 +0,0 @@
<xml
xmlns:genTemplate="http://schemas.microsoft.com/appx/developer/templatestudio">
<genTemplate:Metadata>
<genTemplate:Item Name="generator" Value="Template Studio"/>
<genTemplate:Item Name="wizardVersion" Version="v5.5" />
<genTemplate:Item Name="projectType" Value="NavView" />
<genTemplate:Item Name="framework" Value="MVVMToolkit" />
<genTemplate:Item Name="platform" Value="WinUI" />
<genTemplate:Item Name="appmodel" Value="Desktop" />
</genTemplate:Metadata>
</xml>
@@ -1 +0,0 @@
global using WinUIEx;
@@ -1,47 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net7.0-windows10.0.19041.0</TargetFramework>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<RootNamespace>VDD_Panel</RootNamespace>
<ApplicationIcon>Assets/WindowIcon.ico</ApplicationIcon>
<ApplicationManifest>app.manifest</ApplicationManifest>
<Platforms>x86;x64;arm64</Platforms>
<RuntimeIdentifiers>win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers>
<PublishProfile>Properties\PublishProfiles\win10-$(Platform).pubxml</PublishProfile>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UseWinUI>true</UseWinUI>
<EnableMsixTooling>true</EnableMsixTooling>
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
</PropertyGroup>
<ItemGroup>
<Manifest Include="$(ApplicationManifest)" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.1.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.4.231008000" />
<PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.9" />
<PackageReference Include="WinUIEx" Version="2.3.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\VDD Panel.Core\VDD Panel.Core.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
<ProjectCapability Include="Msix" />
</ItemGroup>
<PropertyGroup Condition="'$(DisableHasPackageAndPublishMenuAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
<HasPackageAndPublishMenu>true</HasPackageAndPublishMenu>
</PropertyGroup>
</Project>
@@ -1,10 +0,0 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace VDD_Panel.ViewModels;
public partial class ConfigureViewModel : ObservableRecipient
{
public ConfigureViewModel()
{
}
}
@@ -1,110 +0,0 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Web.WebView2.Core;
using VDD_Panel.Contracts.Services;
using VDD_Panel.Contracts.ViewModels;
namespace VDD_Panel.ViewModels;
// TODO: Review best practices and distribution guidelines for WebView2.
// https://docs.microsoft.com/microsoft-edge/webview2/get-started/winui
// https://docs.microsoft.com/microsoft-edge/webview2/concepts/developer-guide
// https://docs.microsoft.com/microsoft-edge/webview2/concepts/distribution
public partial class GitHubViewModel : ObservableRecipient, INavigationAware
{
// TODO: Set the default URL to display.
[ObservableProperty]
private Uri source = new("https://github.com/itsmikethetech/Virtual-Display-Driver");
[ObservableProperty]
private bool isLoading = true;
[ObservableProperty]
private bool hasFailures;
public IWebViewService WebViewService
{
get;
}
public GitHubViewModel(IWebViewService webViewService)
{
WebViewService = webViewService;
}
[RelayCommand]
private async Task OpenInBrowser()
{
if (WebViewService.Source != null)
{
await Windows.System.Launcher.LaunchUriAsync(WebViewService.Source);
}
}
[RelayCommand]
private void Reload()
{
WebViewService.Reload();
}
[RelayCommand(CanExecute = nameof(BrowserCanGoForward))]
private void BrowserForward()
{
if (WebViewService.CanGoForward)
{
WebViewService.GoForward();
}
}
private bool BrowserCanGoForward()
{
return WebViewService.CanGoForward;
}
[RelayCommand(CanExecute = nameof(BrowserCanGoBack))]
private void BrowserBack()
{
if (WebViewService.CanGoBack)
{
WebViewService.GoBack();
}
}
private bool BrowserCanGoBack()
{
return WebViewService.CanGoBack;
}
public void OnNavigatedTo(object parameter)
{
WebViewService.NavigationCompleted += OnNavigationCompleted;
}
public void OnNavigatedFrom()
{
WebViewService.UnregisterEvents();
WebViewService.NavigationCompleted -= OnNavigationCompleted;
}
private void OnNavigationCompleted(object? sender, CoreWebView2WebErrorStatus webErrorStatus)
{
IsLoading = false;
BrowserBackCommand.NotifyCanExecuteChanged();
BrowserForwardCommand.NotifyCanExecuteChanged();
if (webErrorStatus != default)
{
HasFailures = true;
}
}
[RelayCommand]
private void OnRetry()
{
HasFailures = false;
IsLoading = true;
WebViewService?.Reload();
}
}
@@ -1,10 +0,0 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace VDD_Panel.ViewModels;
public partial class MainViewModel : ObservableRecipient
{
public MainViewModel()
{
}
}
@@ -1,65 +0,0 @@
using System.Reflection;
using System.Windows.Input;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.UI.Xaml;
using VDD_Panel.Contracts.Services;
using VDD_Panel.Helpers;
using Windows.ApplicationModel;
namespace VDD_Panel.ViewModels;
public partial class SettingsViewModel : ObservableRecipient
{
private readonly IThemeSelectorService _themeSelectorService;
[ObservableProperty]
private ElementTheme _elementTheme;
[ObservableProperty]
private string _versionDescription;
public ICommand SwitchThemeCommand
{
get;
}
public SettingsViewModel(IThemeSelectorService themeSelectorService)
{
_themeSelectorService = themeSelectorService;
_elementTheme = _themeSelectorService.Theme;
_versionDescription = GetVersionDescription();
SwitchThemeCommand = new RelayCommand<ElementTheme>(
async (param) =>
{
if (ElementTheme != param)
{
ElementTheme = param;
await _themeSelectorService.SetThemeAsync(param);
}
});
}
private static string GetVersionDescription()
{
Version version;
if (RuntimeHelper.IsMSIX)
{
var packageVersion = Package.Current.Id.Version;
version = new(packageVersion.Major, packageVersion.Minor, packageVersion.Build, packageVersion.Revision);
}
else
{
version = Assembly.GetExecutingAssembly().GetName().Version!;
}
return $"{"AppDisplayName".GetLocalized()} - {version.Major}.{version.Minor}.{version.Build}.{version.Revision}";
}
}
@@ -1,51 +0,0 @@
using CommunityToolkit.Mvvm.ComponentModel;
using Microsoft.UI.Xaml.Navigation;
using VDD_Panel.Contracts.Services;
using VDD_Panel.Views;
namespace VDD_Panel.ViewModels;
public partial class ShellViewModel : ObservableRecipient
{
[ObservableProperty]
private bool isBackEnabled;
[ObservableProperty]
private object? selected;
public INavigationService NavigationService
{
get;
}
public INavigationViewService NavigationViewService
{
get;
}
public ShellViewModel(INavigationService navigationService, INavigationViewService navigationViewService)
{
NavigationService = navigationService;
NavigationService.Navigated += OnNavigated;
NavigationViewService = navigationViewService;
}
private void OnNavigated(object sender, NavigationEventArgs e)
{
IsBackEnabled = NavigationService.CanGoBack;
if (e.SourcePageType == typeof(SettingsPage))
{
Selected = NavigationViewService.SettingsItem;
return;
}
var selectedItem = NavigationViewService.GetSelectedItem(e.SourcePageType);
if (selectedItem != null)
{
Selected = selectedItem;
}
}
}
@@ -1,12 +0,0 @@
<Page
x:Class="VDD_Panel.Views.ConfigurePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid x:Name="ContentArea">
</Grid>
</Page>
@@ -1,19 +0,0 @@
using Microsoft.UI.Xaml.Controls;
using VDD_Panel.ViewModels;
namespace VDD_Panel.Views;
public sealed partial class ConfigurePage : Page
{
public ConfigureViewModel ViewModel
{
get;
}
public ConfigurePage()
{
ViewModel = App.GetService<ConfigureViewModel>();
InitializeComponent();
}
}
@@ -1,56 +0,0 @@
<Page
x:Class="VDD_Panel.Views.GitHubPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:behaviors="using:VDD_Panel.Behaviors"
behaviors:NavigationViewHeaderBehavior.HeaderMode="Never"
mc:Ignorable="d">
<Grid x:Name="ContentArea">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<WebView2
x:Name="WebView"
Source="{x:Bind ViewModel.Source, Mode=OneWay}" />
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Visibility="{x:Bind ViewModel.IsLoading, Mode=OneWay}">
<ProgressRing IsActive="{x:Bind ViewModel.IsLoading, Mode=OneWay}" />
<TextBlock x:Uid="WebView_Loading" />
</StackPanel>
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Visibility="{x:Bind ViewModel.HasFailures, Mode=OneWay}">
<TextBlock x:Uid="WebView_FailedMessage" HorizontalAlignment="Center" TextWrapping="WrapWholeWords" />
<HyperlinkButton x:Uid="WebView_Reload" Command="{x:Bind ViewModel.ReloadCommand}" HorizontalAlignment="Center" />
</StackPanel>
<Grid Grid.Row="1">
<StackPanel Orientation="Horizontal">
<Button x:Uid="BrowserBackButton" Command="{x:Bind ViewModel.BrowserBackCommand, Mode=OneWay}" Margin="{StaticResource XSmallLeftTopRightBottomMargin}" Padding="{StaticResource XXSmallLeftTopRightBottomMargin}">
<FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72B;" />
</Button>
<Button x:Uid="BrowserForwardButton" Command="{x:Bind ViewModel.BrowserForwardCommand, Mode=OneWay}" Margin="{StaticResource XSmallLeftTopRightBottomMargin}" Padding="{StaticResource XXSmallLeftTopRightBottomMargin}">
<FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72A;" />
</Button>
</StackPanel >
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button x:Uid="ReloadButton" Command="{x:Bind ViewModel.ReloadCommand}" Margin="{StaticResource XSmallLeftTopRightBottomMargin}" Padding="{StaticResource XXSmallLeftTopRightBottomMargin}">
<FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72C;" />
</Button>
<Button x:Uid="OpenInBrowserButton" Command="{x:Bind ViewModel.OpenInBrowserCommand}" Margin="{StaticResource XSmallLeftTopRightBottomMargin}" Padding="{StaticResource XXSmallLeftTopRightBottomMargin}">
<FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE774;" />
</Button>
</StackPanel>
</Grid>
</Grid>
</Page>
@@ -1,22 +0,0 @@
using Microsoft.UI.Xaml.Controls;
using VDD_Panel.ViewModels;
namespace VDD_Panel.Views;
// To learn more about WebView2, see https://docs.microsoft.com/microsoft-edge/webview2/.
public sealed partial class GitHubPage : Page
{
public GitHubViewModel ViewModel
{
get;
}
public GitHubPage()
{
ViewModel = App.GetService<GitHubViewModel>();
InitializeComponent();
ViewModel.WebViewService.Initialize(WebView);
}
}
@@ -1,12 +0,0 @@
<Page
x:Class="VDD_Panel.Views.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid x:Name="ContentArea">
</Grid>
</Page>
@@ -1,19 +0,0 @@
using Microsoft.UI.Xaml.Controls;
using VDD_Panel.ViewModels;
namespace VDD_Panel.Views;
public sealed partial class MainPage : Page
{
public MainViewModel ViewModel
{
get;
}
public MainPage()
{
ViewModel = App.GetService<MainViewModel>();
InitializeComponent();
}
}
@@ -1,67 +0,0 @@
<Page
x:Class="VDD_Panel.Views.SettingsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:helpers="using:VDD_Panel.Helpers"
xmlns:xaml="using:Microsoft.UI.Xaml"
mc:Ignorable="d">
<Page.Resources>
<helpers:EnumToBooleanConverter x:Key="EnumToBooleanConverter" />
</Page.Resources>
<Grid>
<StackPanel
x:Name="ContentArea">
<TextBlock x:Uid="Settings_Personalization" Style="{ThemeResource SubtitleTextBlockStyle}" />
<StackPanel Margin="{StaticResource SmallTopBottomMargin}">
<TextBlock x:Uid="Settings_Theme" />
<StackPanel Margin="{StaticResource XSmallTopMargin}">
<RadioButton
x:Uid="Settings_Theme_Light"
Command="{x:Bind ViewModel.SwitchThemeCommand}"
IsChecked="{x:Bind ViewModel.ElementTheme, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter=Light, Mode=OneWay}"
FontSize="15"
GroupName="AppTheme">
<RadioButton.CommandParameter>
<xaml:ElementTheme>Light</xaml:ElementTheme>
</RadioButton.CommandParameter>
</RadioButton>
<RadioButton
x:Uid="Settings_Theme_Dark"
Command="{x:Bind ViewModel.SwitchThemeCommand}"
IsChecked="{x:Bind ViewModel.ElementTheme, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter=Dark, Mode=OneWay}"
FontSize="15"
GroupName="AppTheme">
<RadioButton.CommandParameter>
<xaml:ElementTheme>Dark</xaml:ElementTheme>
</RadioButton.CommandParameter>
</RadioButton>
<RadioButton
x:Uid="Settings_Theme_Default"
Command="{x:Bind ViewModel.SwitchThemeCommand}"
IsChecked="{x:Bind ViewModel.ElementTheme, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter=Default, Mode=OneWay}"
FontSize="15"
GroupName="AppTheme">
<RadioButton.CommandParameter>
<xaml:ElementTheme>Default</xaml:ElementTheme>
</RadioButton.CommandParameter>
</RadioButton>
</StackPanel>
</StackPanel>
<TextBlock x:Uid="Settings_About" Style="{ThemeResource SubtitleTextBlockStyle}" />
<StackPanel Margin="{StaticResource XSmallTopMargin}">
<TextBlock Text="{x:Bind ViewModel.VersionDescription, Mode=OneWay}" Style="{ThemeResource BodyTextBlockStyle}" />
<TextBlock
x:Uid="Settings_AboutDescription"
Margin="{StaticResource XSmallTopMargin}"
Style="{ThemeResource BodyTextBlockStyle}" />
<HyperlinkButton x:Uid="SettingsPage_PrivacyTermsLink" Margin="{StaticResource SettingsPageHyperlinkButtonMargin}" />
</StackPanel>
</StackPanel>
</Grid>
</Page>
@@ -1,20 +0,0 @@
using Microsoft.UI.Xaml.Controls;
using VDD_Panel.ViewModels;
namespace VDD_Panel.Views;
// TODO: Set the URL for your privacy policy by updating SettingsPage_PrivacyTermsLink.NavigateUri in Resources.resw.
public sealed partial class SettingsPage : Page
{
public SettingsViewModel ViewModel
{
get;
}
public SettingsPage()
{
ViewModel = App.GetService<SettingsViewModel>();
InitializeComponent();
}
}
@@ -1,90 +0,0 @@
<Page
x:Class="VDD_Panel.Views.ShellPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:helpers="using:VDD_Panel.Helpers"
xmlns:behaviors="using:VDD_Panel.Behaviors"
xmlns:i="using:Microsoft.Xaml.Interactivity"
Loaded="OnLoaded">
<Grid>
<Grid x:Name="AppTitleBar"
Canvas.ZIndex="1"
Height="{Binding ElementName=NavigationViewControl, Path=CompactPaneLength}"
IsHitTestVisible="True"
VerticalAlignment="Top">
<Image Source="/Assets/WindowIcon.ico"
HorizontalAlignment="Left"
Width="16"
Height="16" />
<TextBlock x:Name="AppTitleBarText"
VerticalAlignment="Center"
TextWrapping="NoWrap"
Style="{StaticResource CaptionTextBlockStyle}"
Margin="28,0,0,0"/>
</Grid>
<NavigationView
x:Name="NavigationViewControl"
Canvas.ZIndex="0"
IsBackButtonVisible="Visible"
IsBackEnabled="{x:Bind ViewModel.IsBackEnabled, Mode=OneWay}"
SelectedItem="{x:Bind ViewModel.Selected, Mode=OneWay}"
IsSettingsVisible="True"
ExpandedModeThresholdWidth="1280"
DisplayModeChanged="NavigationViewControl_DisplayModeChanged"
Header="{x:Bind ((ContentControl)ViewModel.Selected).Content, Mode=OneWay}">
<NavigationView.MenuItems>
<!--
TODO: Update item titles by updating <x:Uid>.Content entries in Strings/en-us/Resources.resw.
https://docs.microsoft.com/windows/uwp/app-resources/localize-strings-ui-manifest#refer-to-a-string-resource-identifier-from-xaml
TODO: Update item icons by updating FontIcon.Glyph properties.
https://docs.microsoft.com/windows/apps/design/style/segoe-fluent-icons-font#icon-list
-->
<NavigationViewItem x:Uid="Shell_Main" helpers:NavigationHelper.NavigateTo="VDD_Panel.ViewModels.MainViewModel">
<NavigationViewItem.Icon>
<FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xe7c3;"/>
</NavigationViewItem.Icon>
</NavigationViewItem>
<NavigationViewItem x:Uid="Shell_Configure" helpers:NavigationHelper.NavigateTo="VDD_Panel.ViewModels.ConfigureViewModel">
<NavigationViewItem.Icon>
<FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xe7c3;"/>
</NavigationViewItem.Icon>
</NavigationViewItem>
<NavigationViewItem x:Uid="Shell_GitHub" helpers:NavigationHelper.NavigateTo="VDD_Panel.ViewModels.GitHubViewModel">
<NavigationViewItem.Icon>
<FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xe774;"/>
</NavigationViewItem.Icon>
</NavigationViewItem>
</NavigationView.MenuItems>
<NavigationView.HeaderTemplate>
<DataTemplate>
<Grid>
<TextBlock
Text="{Binding}"
Style="{ThemeResource TitleTextBlockStyle}" />
</Grid>
</DataTemplate>
</NavigationView.HeaderTemplate>
<i:Interaction.Behaviors>
<behaviors:NavigationViewHeaderBehavior
DefaultHeader="{x:Bind ((ContentControl)ViewModel.Selected).Content, Mode=OneWay}">
<behaviors:NavigationViewHeaderBehavior.DefaultHeaderTemplate>
<DataTemplate>
<Grid>
<TextBlock
Text="{Binding}"
Style="{ThemeResource TitleTextBlockStyle}" />
</Grid>
</DataTemplate>
</behaviors:NavigationViewHeaderBehavior.DefaultHeaderTemplate>
</behaviors:NavigationViewHeaderBehavior>
</i:Interaction.Behaviors>
<Grid Margin="{StaticResource NavigationViewPageContentMargin}">
<Frame x:Name="NavigationFrame" />
</Grid>
</NavigationView>
</Grid>
</Page>
@@ -1,85 +0,0 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using VDD_Panel.Contracts.Services;
using VDD_Panel.Helpers;
using VDD_Panel.ViewModels;
using Windows.System;
namespace VDD_Panel.Views;
// TODO: Update NavigationViewItem titles and icons in ShellPage.xaml.
public sealed partial class ShellPage : Page
{
public ShellViewModel ViewModel
{
get;
}
public ShellPage(ShellViewModel viewModel)
{
ViewModel = viewModel;
InitializeComponent();
ViewModel.NavigationService.Frame = NavigationFrame;
ViewModel.NavigationViewService.Initialize(NavigationViewControl);
// TODO: Set the title bar icon by updating /Assets/WindowIcon.ico.
// A custom title bar is required for full window theme and Mica support.
// https://docs.microsoft.com/windows/apps/develop/title-bar?tabs=winui3#full-customization
App.MainWindow.ExtendsContentIntoTitleBar = true;
App.MainWindow.SetTitleBar(AppTitleBar);
App.MainWindow.Activated += MainWindow_Activated;
AppTitleBarText.Text = "AppDisplayName".GetLocalized();
}
private void OnLoaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
TitleBarHelper.UpdateTitleBar(RequestedTheme);
KeyboardAccelerators.Add(BuildKeyboardAccelerator(VirtualKey.Left, VirtualKeyModifiers.Menu));
KeyboardAccelerators.Add(BuildKeyboardAccelerator(VirtualKey.GoBack));
}
private void MainWindow_Activated(object sender, WindowActivatedEventArgs args)
{
App.AppTitlebar = AppTitleBarText as UIElement;
}
private void NavigationViewControl_DisplayModeChanged(NavigationView sender, NavigationViewDisplayModeChangedEventArgs args)
{
AppTitleBar.Margin = new Thickness()
{
Left = sender.CompactPaneLength * (sender.DisplayMode == NavigationViewDisplayMode.Minimal ? 2 : 1),
Top = AppTitleBar.Margin.Top,
Right = AppTitleBar.Margin.Right,
Bottom = AppTitleBar.Margin.Bottom
};
}
private static KeyboardAccelerator BuildKeyboardAccelerator(VirtualKey key, VirtualKeyModifiers? modifiers = null)
{
var keyboardAccelerator = new KeyboardAccelerator() { Key = key };
if (modifiers.HasValue)
{
keyboardAccelerator.Modifiers = modifiers.Value;
}
keyboardAccelerator.Invoked += OnKeyboardAcceleratorInvoked;
return keyboardAccelerator;
}
private static void OnKeyboardAcceleratorInvoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
{
var navigationService = App.GetService<INavigationService>();
var result = navigationService.GoBack();
args.Handled = result;
}
}
@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="VDD_Panel.app"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
</windowsSettings>
</application>
</assembly>
@@ -1,6 +0,0 @@
{
"LocalSettingsOptions": {
"ApplicationDataFolder": "VDD_Panel/ApplicationData",
"LocalSettingsFile": "LocalSettings.json"
}
}
+5 -15
View File
@@ -7,23 +7,13 @@ if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdent
}
}
$repoName = "PSGallery"
$moduleName1 = "DisplayConfig"
$moduleName2 = "MonitorConfig"
if (!(Get-PSRepository -Name $repoName) -OR !(Find-Module -Name $moduleName1 | Where-Object {$_.Name -eq $moduleName1}) -OR !(Find-Module -Name $moduleName2 | Where-Object {$_.Name -eq $moduleName2})) {
& .\dep_fix.ps1
}
# Install dependencies if required
. "$PSScriptRoot\set-dependencies.ps1"
# Import the local module
$dpth = Get-Module -ListAvailable $moduleName1 | select path | Select-Object -ExpandProperty path
import-module -name $dpth -InformationAction:Ignore -Verbose:$false -WarningAction:SilentlyContinue
# Getting the correct display
$disp = Get-DisplayInfo | Where-Object { $_.DisplayName -eq "VDD by MTT" }
# Import the other localmodule
$mpth = Get-Module -ListAvailable $moduleName2 | select path | Select-Object -ExpandProperty path
import-module -name $mpth -InformationAction:Ignore -Verbose:$false -WarningAction:SilentlyContinue
$disp = Get-Monitor | Select-String -Pattern "MTT1337" | Select-Object LineNumber | Select-Object -ExpandProperty LineNumber
$bpcc = Get-DisplayColorInfo -DisplayId $disp | Select-Object BitsPerColorChannel | Select-Object -ExpandProperty BitsPerColorChannel
$bpcc = Get-DisplayColorInfo -DisplayId $disp.DisplayId | Select-Object BitsPerColorChannel | Select-Object -ExpandProperty BitsPerColorChannel
if ( $bpcc -is [int] ) {
if ( $bpcc -gt 8 ) {
+18 -7
View File
@@ -1,9 +1,20 @@
#Scripts
# Scripts
This is a collection of Powershell scripts, written during the whole driver development. There haven't been a focus on keeping the scripts "up to date" all the time. Which means changes that might have occurred in the modules that these scripts depend upon, haven't been corrected either.
This is a collection of Powershell scripts, written during the whole driver development. PR's are welcome for improvements or other/more functions. There haven't been a focus on keeping the scripts "up to date" all the time. Which means changes that might have occurred in the modules that these scripts depend upon, haven't been corrected either. These are more ment as a framework for "tinkers" to make use of Powershell to change settings on the fly. To use these, you should be at least be comfortable with Powershell and understand Admin privilegiets, risk/reward.
This is more ment as a framework for "tinkers" to make use of Powershell to change settings on the fly.
To use these, you should be at least be comfortable with Powershell and understand Admin privilegiets, risk/reward.
PR's are welcome for improvements or other/more functions.
Anyway here is a short description of each script:
| Script | Description |
| ---------------------- | ---------------- |
| [changeres‑VDD.ps1](changeres-VDD.ps1) | Hot‑swaps the virtual panel’s resolution to the width and height you pass on the command line. |
| [get_disp_num.ps1](get_disp_num.ps1) | Returns the numeric adapter ID of the VDD screen by scanning WMI for your custom “MTT1337” monitor identifier. |
| [HDRswitch‑VDD.ps1](HDRswitch-VDD.ps1) | Flips the virtual screen between SDR (8‑bit) and HDR (10‑bit) colour modes in one click. Unsure if it works anylonger, since changes in modules |
| [modules_install.bat](modules_install.bat) | Opens an elevated PowerShell session that installs the DisplayConfig and MonitorConfig modules so every helper script has its prerequisites. |
| [primary‑VDD.ps1](primary-VDD.ps1) | Makes the virtual display the Windows primary so you can stream or remote‑desktop from a headless rig. |
| [refreshrate‑VDD.ps1](refreshrate.ps1) | Changes the VDD monitor’s refresh rate (30‑‑500 Hz) after validating the value against a safe list. |
| [rotate‑VDD.ps1](rotate-VDD.ps1) | Rotates the virtual display 90°, 180°, or 270° by calling DisplayConfig with the matching rotation token. |
| [scale‑VDD.ps1](scale-VDD.ps1) | Sets or resets DPI scaling on the virtual monitor, respecting Windows’ maximum allowed scale factor. |
| [set‑dependencies.ps1](set-dependencies.ps1) | Verifies the exact module versions required, installs or imports them on demand, and aborts downstream execution if anything is missing. |
| [silent‑install.ps1](silent-install.ps1) | Silently fetches the latest signed Virtual Display Driver from GitHub and installs it via Nefcon, then tidies up the temp workspace. |
| [toggle‑VDD.ps1](toggle-VDD.ps1) | A one‑click PowerShell switch that first elevates itself to admin, then enables or disables your Virtual Display Driver and immediately flips Windows between Extended and Cloned desktops, perfect for streamers who need to bring a virtual monitor online or offline on demand. |
| [virtual-driver-manager.ps1](virtual-driver-manager.ps1) | A comprehensive script to manage the Virtual Display Driver. It can install, uninstall, enable, disable, toggle, and check the status of the driver. |
| [winp‑VDD.ps1](winp-VDD.ps1) | A lightweight companion script that leaves the driver untouched and simply yo‑yos Windows between Extend and Clone modes, giving you an instant “presentation toggle” when the virtual display should stay permanently enabled. |
+19 -31
View File
@@ -1,39 +1,27 @@
param(
[Parameter(Mandatory, Position=0)]
[Alias("X","HorizontalResolution")]
[int]$xres,
[Parameter(Mandatory, Position=1)]
[Alias("Y","VerticalResolution")]
[int]$yres
)
# Self-elevate the script if required
if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
$CommandLine = "-File `"" + $MyInvocation.MyCommand.Path + "`" " + $MyInvocation.UnboundArguments
Start-Process -FilePath PowerShell.exe -Verb Runas -ArgumentList $CommandLine
Exit
$CommandLine = "-File `"" + $MyInvocation.MyCommand.Path + "`" "
$MyInvocation.BoundParameters.GetEnumerator() | ForEach-Object { $CommandLine += "-$($_.Key):$($_.Value) " }
Start-Process -WorkingDirectory $PSScriptRoot -FilePath PowerShell.exe -Verb Runas -ArgumentList $CommandLine
exit
}
}
$repoName = "PSGallery"
$moduleName1 = "DisplayConfig"
$moduleName2 = "MonitorConfig"
if (!(Get-PSRepository -Name $repoName) -OR !(Find-Module -Name $moduleName1 | Where-Object {$_.Name -eq $moduleName1}) -OR !(Find-Module -Name $moduleName2 | Where-Object {$_.Name -eq $moduleName2})) {
& .\dep_fix.ps1
}
# Install dependencies if required
. "$PSScriptRoot\set-dependencies.ps1"
# Getting the correct display
$disp = Get-DisplayInfo | Where-Object { $_.DisplayName -eq "VDD by MTT" }
# Import the local module
$dpth = Get-Module -ListAvailable $moduleName1 | select path | Select-Object -ExpandProperty path
import-module -name $dpth -InformationAction:Ignore -Verbose:$false -WarningAction:SilentlyContinue -Confirm:$false
# Import the other localmodule
$mpth = Get-Module -ListAvailable $moduleName2 | select path | Select-Object -ExpandProperty path
import-module -name $mpth -InformationAction:Ignore -Verbose:$false -WarningAction:SilentlyContinue -Confirm:$false
# Check if there are enough arguments
$numArgs = $args.Count
switch ($numArgs) {
0 { Write-Error "This script requires at least 2 arguments Xres Yres."; break }
1 { Write-Error "This script requires at least 2 arguments Xres Yres."; break }
2 { $disp = Get-Monitor | Select-String -Pattern "MTT1337" | Select-Object LineNumber | Select-Object -ExpandProperty LineNumber
$vres = $args[0]
$hres = $args[1]
continue
}
default { Write-Error "Invalid number of arguments: $numArgs"; break }
}
# Setting the resolution on the correct display.
Get-DisplayConfig | Set-DisplayResolution -DisplayId $disp -Width $vres -Height $hres | Use-DisplayConfig
# Setting the resolution on the display
Set-DisplayResolution -DisplayId $disp.DisplayId -Width $xres -Height $yres
-32
View File
@@ -1,32 +0,0 @@
# Define the repository name and URL
$repoName = "PSGallery"
$repoUrl = "https://www.powershellgallery.com/api/v2"
# Check if the repository is registered
if (-not (Get-PSRepository -Name $repoName)) {
# Register the repository
Register-PSRepository -Name $repoName -SourceLocation $repoUrl -Confirm:$false -InformationAction:Ignore -WarningAction:SilentlyContinue
}
#Trust the repo, either its allready installed or newly added
Set-PSRepository -Name $repoName -InstallationPolicy Trusted -InformationAction:Ignore -WarningAction:SilentlyContinue
# Define the module name and version
$moduleName1 = "DisplayConfig"
$version1 = "1.1.1"
# Define the module name and version
$moduleName2 = "MonitorConfig"
$version2 = "1.0.3"
# Check if the module1 is installed
if (-not (Get-InstalledModule -Name $moduleName1 -MinimumVersion $version1)) {
# Save the module
Save-Module -Name $moduleName1 -Repository $repoName -RequiredVersion $version1 -Confirm:$false -InformationAction:Ignore -WarningAction:SilentlyContinue
}
# Check if the module2 is installed
if (-not (Get-InstalledModule -Name $moduleName2 -MinimumVersion $version2)) {
# Save the module
Save-Module -Name $moduleName2 -Repository $repoName -RequiredVersion $version2 -Confirm:$false -InformationAction:Ignore -WarningAction:SilentlyContinue
}
+12
View File
@@ -0,0 +1,12 @@
# One-liner to get the logicalname of the first VDD
# You can alter the script -First 3, would make the third in the list,
# or -Last 2 would give second from last.
$dispnum = (Get-Monitor | Where-Object { $_.InstanceName -like '*MTT1337*' } | Sort-Object { [int] (($_.InstanceName -match 'UID(\d+)') -and $Matches[1]) } | Select-Object -First 1).LogicalDisplay.DeviceName
# Echo the result to console
Write-Host $dispnum
# Pause the console from closeing when executed from VDC
Write-Host "Press any key to continue ..."
$host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") | Out-Null
+20
View File
@@ -0,0 +1,20 @@
@echo off
:: Use PowerShell for elevation check and execution
powershell -NoProfile -ExecutionPolicy Bypass -Command ^
"$elevated = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator');" ^
"if (-not $elevated) {" ^
"$CommandLine = '-File \"' + $MyInvocation.MyCommand.Path + '\" ' + $MyInvocation.UnboundArguments;" ^
"Start-Process -FilePath PowerShell.exe -Verb Runas -ArgumentList $CommandLine;" ^
"Exit" ^
"} else {" ^
"Install-Module -Name DisplayConfig -Scope AllUsers -Force -AllowClobber;" ^
"Install-Module -Name MonitorConfig -Scope AllUsers -Force -AllowClobber;" ^
"if ($?) {" ^
"Write-Output 'Modules installed successfully.'" ^
"} else {" ^
"Write-Output 'An error occurred while installing the modules.'" ^
"}" ^
"}"
pause
+4 -15
View File
@@ -7,20 +7,9 @@ if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdent
}
}
$repoName = "PSGallery"
$moduleName1 = "DisplayConfig"
$moduleName2 = "MonitorConfig"
if (!(Get-PSRepository -Name $repoName) -OR !(Find-Module -Name $moduleName1 | Where-Object {$_.Name -eq $moduleName1}) -OR !(Find-Module -Name $moduleName2 | Where-Object {$_.Name -eq $moduleName2})) {
& .\dep_fix.ps1
}
# Install dependencies if required
. "$PSScriptRoot\set-dependencies.ps1"
$disp = Get-DisplayInfo | Where-Object { $_.DisplayName -eq "VDD by MTT" }
# Import the local module
$dpth = Get-Module -ListAvailable $moduleName1 | select path | Select-Object -ExpandProperty path; import-module -name $dpth
# Import the other localmodule
$mpth = Get-Module -ListAvailable $moduleName2 | select path | Select-Object -ExpandProperty path; import-module -name $mpth
$disp = Get-Monitor | Select-String -Pattern "MTT1337" | Select-Object LineNumber | Select-Object -ExpandProperty LineNumber
Set-DisplayPrimary -DisplayId $disp
Set-DisplayPrimary -DisplayId $disp.DisplayId
Loaded 100 of 174 files, more files were not shown because too many files have changed in this diff. Show more