[
  {
    "path": ".gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore\n\n# User-specific files\n*.rsuser\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Mono auto generated files\nmono_crash.*\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\n[Ww][Ii][Nn]32/\n[Aa][Rr][Mm]/\n[Aa][Rr][Mm]64/\nbld/\n[Bb]in/\n[Oo]bj/\n[Ll]og/\n[Ll]ogs/\n\n# Visual Studio 2015/2017 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# Visual Studio 2017 auto generated files\nGenerated\\ Files/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUnit\n*.VisualState.xml\nTestResult.xml\nnunit-*.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# Benchmark Results\nBenchmarkDotNet.Artifacts/\n\n# .NET Core\nproject.lock.json\nproject.fragment.lock.json\nartifacts/\n\n# ASP.NET Scaffolding\nScaffoldingReadMe.txt\n\n# StyleCop\nStyleCopReport.xml\n\n# Files built by Visual Studio\n*_i.c\n*_p.c\n*_h.h\n*.ilk\n*.meta\n*.obj\n*.iobj\n*.pch\n*.pdb\n*.ipdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*_wpftmp.csproj\n*.log\n*.tlog\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n*.VC.db\n*.VC.VC.opendb\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# Visual Studio Trace Files\n*.e2e\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# AxoCover is a Code Coverage Tool\n.axoCover/*\n!.axoCover/settings.json\n\n# Coverlet is a free, cross platform Code Coverage Tool\ncoverage*.json\ncoverage*.xml\ncoverage*.info\n\n# Visual Studio code coverage results\n*.coverage\n*.coveragexml\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# Note: Comment the next line if you want to checkin your web deploy settings,\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# Microsoft Azure Web App publish settings. Comment the next line if you want to\n# checkin your Azure Web App publish settings, but sensitive information contained\n# in these scripts will be unencrypted\nPublishScripts/\n\n# NuGet Packages\n*.nupkg\n# NuGet Symbol Packages\n*.snupkg\n# The packages folder can be ignored because of Package Restore\n**/[Pp]ackages/*\n# except build/, which is used as an MSBuild target.\n!**/[Pp]ackages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/[Pp]ackages/repositories.config\n# NuGet v3's project.json files produces more ignorable files\n*.nuget.props\n*.nuget.targets\n\n# Nuget personal access tokens and Credentials\n# nuget.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Windows Store app package directories and files\nAppPackages/\nBundleArtifacts/\nPackage.StoreAssociation.xml\n_pkginfo.txt\n*.appx\n*.appxbundle\n*.appxupload\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!?*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.jfm\n*.pfx\n*.publishsettings\norleans.codegen.cs\n\n# Including strong name files can present a security risk\n# (https://github.com/github/gitignore/pull/2483#issue-259490424)\n#*.snk\n\n# Since there are multiple workflows, uncomment next line to ignore bower_components\n# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)\n#bower_components/\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\nServiceFabricBackup/\n*.rptproj.bak\n\n# SQL Server files\n*.mdf\n*.ldf\n*.ndf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n*.rptproj.rsuser\n*- [Bb]ackup.rdl\n*- [Bb]ackup ([0-9]).rdl\n*- [Bb]ackup ([0-9][0-9]).rdl\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\nnode_modules/\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)\n*.vbw\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\npaket-files/\n\n# FAKE - F# Make\n.fake/\n\n# CodeRush personal settings\n.cr/personal\n\n# Python Tools for Visual Studio (PTVS)\n__pycache__/\n*.pyc\n\n# Cake - Uncomment if you are using it\n# tools/**\n# !tools/packages.config\n\n# Tabs Studio\n*.tss\n\n# Telerik's JustMock configuration file\n*.jmconfig\n\n# BizTalk build output\n*.btp.cs\n*.btm.cs\n*.odx.cs\n*.xsd.cs\n\n# OpenCover UI analysis results\nOpenCover/\n\n# Azure Stream Analytics local run output\nASALocalRun/\n\n# MSBuild Binary and Structured Log\n*.binlog\n\n# NVidia Nsight GPU debugger configuration file\n*.nvuser\n\n# MFractors (Xamarin productivity tool) working folder\n.mfractor/\n\n# Local History for Visual Studio\n.localhistory/\n\n# BeatPulse healthcheck temp database\nhealthchecksdb\n\n# Backup folder for Package Reference Convert tool in Visual Studio 2017\nMigrationBackup/\n\n# Ionide (cross platform F# VS Code tools) working folder\n.ionide/\n\n# Fody - auto-generated XML schema\nFodyWeavers.xsd\n\n# VS Code files for those working on multiple tools\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n!.vscode/extensions.json\n*.code-workspace\n\n# Local History for Visual Studio Code\n.history/\n\n# Windows Installer files from build outputs\n*.cab\n*.msi\n*.msix\n*.msm\n*.msp\n\n# JetBrains Rider\n.idea/\n*.sln.iml\nAutoVersion.cs\n"
  },
  {
    "path": "Bridge/Agent.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System.Collections.Generic;\nusing System.Reflection;\nusing System.Resources;\n\nnamespace VirtualSpace\n{\n    public static class Agent\n    {\n        public static readonly Dictionary<string, string> ValidLangs = new()\n        {\n            {\"en\", \"English\"},\n            {\"zh-Hans\", \"中文(简体)\"}\n        };\n\n        public static ResourceManager Langs = new(\n            Assembly.GetExecutingAssembly().GetName().Name + \".Resources.Langs.WinFormStrings\",\n            typeof( Agent ).Assembly );\n\n        public static ResourceManager Images = new(\n            Assembly.GetExecutingAssembly().GetName().Name + \".Resources.Images.Images\",\n            typeof( Agent ).Assembly );\n    }\n}"
  },
  {
    "path": "Bridge/Behavior.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\n\nnamespace VirtualSpace.Config.Events.Entity\n{\n    public class Behavior\n    {\n        public IntPtr Handle;\n        public string RuleName;\n        public string WindowTitle;\n        public int    MoveToDesktop { get; set; } = -1;\n        public bool   FollowWindow  { get; set; } = true;\n        public bool   PinWindow     { get; set; }\n        public bool   PinApp        { get; set; }\n        public int    MoveToScreen  { get; set; } = -1;\n        public bool   HideFromView  { get; set; }\n        \n        public Behavior Clone()\n        {\n            return new Behavior\n            {\n                Handle = Handle,\n                RuleName = RuleName,\n                WindowTitle = WindowTitle,\n                MoveToDesktop = MoveToDesktop,\n                FollowWindow = FollowWindow,\n                PinWindow = PinWindow,\n                PinApp = PinApp,\n                MoveToScreen = MoveToScreen,\n                HideFromView = HideFromView\n            };\n        }\n    }\n}"
  },
  {
    "path": "Bridge/Bridge.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFrameworks>net6.0-windows</TargetFrameworks>\n        <Nullable>enable</Nullable>\n        <LangVersion>9</LangVersion>\n    </PropertyGroup>\n\n    <ItemGroup>\n      <Compile Update=\"Resources\\Langs\\WinFormStrings.Designer.cs\">\n        <DependentUpon>WinFormStrings.resx</DependentUpon>\n        <DesignTime>True</DesignTime>\n        <AutoGen>True</AutoGen>\n      </Compile>\n      <Compile Update=\"Resources\\Langs\\WinFormStrings.zh-Hans.Designer.cs\">\n        <DependentUpon>WinFormStrings.zh-Hans.resx</DependentUpon>\n        <DesignTime>True</DesignTime>\n        <AutoGen>True</AutoGen>\n      </Compile>\n      <Compile Update=\"Resources\\Images\\Images.Designer.cs\">\n        <DesignTime>True</DesignTime>\n        <AutoGen>True</AutoGen>\n        <DependentUpon>Images.resx</DependentUpon>\n      </Compile>\n    </ItemGroup>\n\n    <ItemGroup>\n      <EmbeddedResource Update=\"Resources\\Langs\\WinFormStrings.resx\">\n        <LastGenOutput>WinFormStrings.Designer.cs</LastGenOutput>\n        <Generator>ResXFileCodeGenerator</Generator>\n      </EmbeddedResource>\n      <EmbeddedResource Update=\"Resources\\Langs\\WinFormStrings.zh-Hans.resx\">\n        <LastGenOutput>WinFormStrings.zh-Hans.Designer.cs</LastGenOutput>\n        <Generator>ResXFileCodeGenerator</Generator>\n      </EmbeddedResource>\n      <EmbeddedResource Update=\"Resources\\Images\\Images.resx\">\n        <Generator>ResXFileCodeGenerator</Generator>\n        <LastGenOutput>Images.Designer.cs</LastGenOutput>\n      </EmbeddedResource>\n    </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "Bridge/COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "Bridge/Channels.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System.Threading.Channels;\nusing VirtualSpace.Config.Events.Entity;\n\nnamespace VirtualSpace.Commons\n{\n    public static class Channels\n    {\n        public static readonly Channel<Behavior>                   ActionChannel               = Channel.CreateUnbounded<Behavior>();\n        public static readonly Channel<Window>                     VisibleWindowsChannel       = Channel.CreateUnbounded<Window>();\n        public static readonly Channel<VirtualDesktopNotification> VirtualDesktopNotifications = Channel.CreateUnbounded<VirtualDesktopNotification>();\n    }\n}"
  },
  {
    "path": "Bridge/Interfaces/IAppController.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\n\nnamespace VirtualSpace\n{\n    public interface IAppController\n    {\n        public void BringToTop();\n        public void SetMainWindowHandle( IntPtr handle );\n        public void Quit();\n        public void RenderDesktopArrangementButtons( string selectedDa );\n        public void CreateRuleFromWindowHandle( IntPtr      handle );\n    }\n}"
  },
  {
    "path": "Bridge/Interfaces/IDesktop.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nnamespace VirtualSpace\n{\n    public interface IDesktop\n    {\n        public void MakeVisible();\n    }\n}"
  },
  {
    "path": "Bridge/Resources/Images/Images.Designer.cs",
    "content": "﻿//------------------------------------------------------------------------------\n// <auto-generated>\n//     此代码由工具生成。\n//     运行时版本:4.0.30319.42000\n//\n//     对此文件的更改可能会导致不正确的行为，并且如果\n//     重新生成代码，这些更改将会丢失。\n// </auto-generated>\n//------------------------------------------------------------------------------\n\nnamespace Bridge.Resources.Images {\n    using System;\n    \n    \n    /// <summary>\n    ///   一个强类型的资源类，用于查找本地化的字符串等。\n    /// </summary>\n    // 此类是由 StronglyTypedResourceBuilder\n    // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。\n    // 若要添加或移除成员，请编辑 .ResX 文件，然后重新运行 ResGen\n    // (以 /str 作为命令选项)，或重新生成 VS 项目。\n    [global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Resources.Tools.StronglyTypedResourceBuilder\", \"17.0.0.0\")]\n    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]\n    internal class Images {\n        \n        private static global::System.Resources.ResourceManager resourceMan;\n        \n        private static global::System.Globalization.CultureInfo resourceCulture;\n        \n        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute(\"Microsoft.Performance\", \"CA1811:AvoidUncalledPrivateCode\")]\n        internal Images() {\n        }\n        \n        /// <summary>\n        ///   返回此类使用的缓存的 ResourceManager 实例。\n        /// </summary>\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\n        internal static global::System.Resources.ResourceManager ResourceManager {\n            get {\n                if (object.ReferenceEquals(resourceMan, null)) {\n                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager(\"Bridge.Resources.Images.Images\", typeof(Images).Assembly);\n                    resourceMan = temp;\n                }\n                return resourceMan;\n            }\n        }\n        \n        /// <summary>\n        ///   重写当前线程的 CurrentUICulture 属性，对\n        ///   使用此强类型资源类的所有资源查找执行重写。\n        /// </summary>\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\n        internal static global::System.Globalization.CultureInfo Culture {\n            get {\n                return resourceCulture;\n            }\n            set {\n                resourceCulture = value;\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] AboutLogo_2 {\n            get {\n                object obj = ResourceManager.GetObject(\"AboutLogo_2\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Big0Black {\n            get {\n                object obj = ResourceManager.GetObject(\"Big0Black\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Big0White {\n            get {\n                object obj = ResourceManager.GetObject(\"Big0White\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Big1Black {\n            get {\n                object obj = ResourceManager.GetObject(\"Big1Black\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Big1White {\n            get {\n                object obj = ResourceManager.GetObject(\"Big1White\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Big2Black {\n            get {\n                object obj = ResourceManager.GetObject(\"Big2Black\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Big2White {\n            get {\n                object obj = ResourceManager.GetObject(\"Big2White\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Big3Black {\n            get {\n                object obj = ResourceManager.GetObject(\"Big3Black\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Big3White {\n            get {\n                object obj = ResourceManager.GetObject(\"Big3White\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Big4Black {\n            get {\n                object obj = ResourceManager.GetObject(\"Big4Black\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Big4White {\n            get {\n                object obj = ResourceManager.GetObject(\"Big4White\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Big5Black {\n            get {\n                object obj = ResourceManager.GetObject(\"Big5Black\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Big5White {\n            get {\n                object obj = ResourceManager.GetObject(\"Big5White\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Big6Black {\n            get {\n                object obj = ResourceManager.GetObject(\"Big6Black\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Big6White {\n            get {\n                object obj = ResourceManager.GetObject(\"Big6White\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Big7Black {\n            get {\n                object obj = ResourceManager.GetObject(\"Big7Black\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Big7White {\n            get {\n                object obj = ResourceManager.GetObject(\"Big7White\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Big8Black {\n            get {\n                object obj = ResourceManager.GetObject(\"Big8Black\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Big8White {\n            get {\n                object obj = ResourceManager.GetObject(\"Big8White\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Big9Black {\n            get {\n                object obj = ResourceManager.GetObject(\"Big9Black\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Big9White {\n            get {\n                object obj = ResourceManager.GetObject(\"Big9White\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Small0Black {\n            get {\n                object obj = ResourceManager.GetObject(\"Small0Black\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Small0White {\n            get {\n                object obj = ResourceManager.GetObject(\"Small0White\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Small1Black {\n            get {\n                object obj = ResourceManager.GetObject(\"Small1Black\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Small1White {\n            get {\n                object obj = ResourceManager.GetObject(\"Small1White\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Small2Black {\n            get {\n                object obj = ResourceManager.GetObject(\"Small2Black\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Small2White {\n            get {\n                object obj = ResourceManager.GetObject(\"Small2White\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Small3Black {\n            get {\n                object obj = ResourceManager.GetObject(\"Small3Black\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Small3White {\n            get {\n                object obj = ResourceManager.GetObject(\"Small3White\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Small4Black {\n            get {\n                object obj = ResourceManager.GetObject(\"Small4Black\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Small4White {\n            get {\n                object obj = ResourceManager.GetObject(\"Small4White\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Small5Black {\n            get {\n                object obj = ResourceManager.GetObject(\"Small5Black\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Small5White {\n            get {\n                object obj = ResourceManager.GetObject(\"Small5White\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Small6Black {\n            get {\n                object obj = ResourceManager.GetObject(\"Small6Black\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Small6White {\n            get {\n                object obj = ResourceManager.GetObject(\"Small6White\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Small7Black {\n            get {\n                object obj = ResourceManager.GetObject(\"Small7Black\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Small7White {\n            get {\n                object obj = ResourceManager.GetObject(\"Small7White\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Small8Black {\n            get {\n                object obj = ResourceManager.GetObject(\"Small8Black\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Small8White {\n            get {\n                object obj = ResourceManager.GetObject(\"Small8White\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Small9Black {\n            get {\n                object obj = ResourceManager.GetObject(\"Small9Black\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] Small9White {\n            get {\n                object obj = ResourceManager.GetObject(\"Small9White\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] TrayIcon {\n            get {\n                object obj = ResourceManager.GetObject(\"TrayIcon\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] TrayIconBack_Black {\n            get {\n                object obj = ResourceManager.GetObject(\"TrayIconBack_Black\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] TrayIconBack_Default {\n            get {\n                object obj = ResourceManager.GetObject(\"TrayIconBack_Default\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Byte[] 类型的本地化资源。\n        /// </summary>\n        internal static byte[] TrayIconBack_White {\n            get {\n                object obj = ResourceManager.GetObject(\"TrayIconBack_White\", resourceCulture);\n                return ((byte[])(obj));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Bridge/Resources/Images/Images.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <assembly alias=\"System.Windows.Forms\" name=\"System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\" />\n  <data name=\"AboutLogo_2\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\aboutlogo_2.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Big0Black\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\big0black.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Big0White\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\big0white.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Big1Black\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\big1black.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Big1White\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\big1white.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Big2Black\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\big2black.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Big2White\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\big2white.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Big3Black\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\big3black.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Big3White\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\big3white.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Big4Black\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\big4black.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Big4White\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\big4white.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Big5Black\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\big5black.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Big5White\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\big5white.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Big6Black\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\big6black.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Big6White\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\big6white.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Big7Black\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\big7black.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Big7White\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\big7white.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Big8Black\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\big8black.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Big8White\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\big8white.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Big9Black\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\big9black.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Big9White\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\big9white.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Small0Black\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\small0black.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Small0White\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\small0white.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Small1Black\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\small1black.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Small1White\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\small1white.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Small2Black\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\small2black.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Small2White\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\small2white.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Small3Black\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\small3black.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Small3White\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\small3white.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Small4Black\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\small4black.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Small4White\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\small4white.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Small5Black\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\small5black.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Small5White\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\small5white.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Small6Black\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\small6black.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Small6White\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\small6white.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Small7Black\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\small7black.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Small7White\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\small7white.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Small8Black\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\small8black.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Small8White\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\small8white.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Small9Black\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\small9black.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"Small9White\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\small9white.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"TrayIcon\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\trayicon.ico;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"TrayIconBack_Black\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\trayiconback_black.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"TrayIconBack_Default\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\trayiconback_default.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"TrayIconBack_White\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\trayiconback_white.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n</root>"
  },
  {
    "path": "Bridge/Resources/Langs/WinFormStrings.Designer.cs",
    "content": "﻿//------------------------------------------------------------------------------\n// <auto-generated>\n//     此代码由工具生成。\n//     运行时版本:4.0.30319.42000\n//\n//     对此文件的更改可能会导致不正确的行为，并且如果\n//     重新生成代码，这些更改将会丢失。\n// </auto-generated>\n//------------------------------------------------------------------------------\n\nnamespace Bridge.Resources.Langs {\n    using System;\n    \n    \n    /// <summary>\n    ///   一个强类型的资源类，用于查找本地化的字符串等。\n    /// </summary>\n    // 此类是由 StronglyTypedResourceBuilder\n    // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。\n    // 若要添加或移除成员，请编辑 .ResX 文件，然后重新运行 ResGen\n    // (以 /str 作为命令选项)，或重新生成 VS 项目。\n    [global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Resources.Tools.StronglyTypedResourceBuilder\", \"17.0.0.0\")]\n    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]\n    internal class WinFormStrings {\n        \n        private static global::System.Resources.ResourceManager resourceMan;\n        \n        private static global::System.Globalization.CultureInfo resourceCulture;\n        \n        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute(\"Microsoft.Performance\", \"CA1811:AvoidUncalledPrivateCode\")]\n        internal WinFormStrings() {\n        }\n        \n        /// <summary>\n        ///   返回此类使用的缓存的 ResourceManager 实例。\n        /// </summary>\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\n        internal static global::System.Resources.ResourceManager ResourceManager {\n            get {\n                if (object.ReferenceEquals(resourceMan, null)) {\n                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager(\"Bridge.Resources.Langs.WinFormStrings\", typeof(WinFormStrings).Assembly);\n                    resourceMan = temp;\n                }\n                return resourceMan;\n            }\n        }\n        \n        /// <summary>\n        ///   重写当前线程的 CurrentUICulture 属性，对\n        ///   使用此强类型资源类的所有资源查找执行重写。\n        /// </summary>\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\n        internal static global::System.Globalization.CultureInfo Culture {\n            get {\n                return resourceCulture;\n            }\n            set {\n                resourceCulture = value;\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Current Desktop:  的本地化字符串。\n        /// </summary>\n        internal static string Cluster_Notification_SVD_Current {\n            get {\n                return ResourceManager.GetString(\"Cluster.Notification.SVD.Current\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Last Desktop:  的本地化字符串。\n        /// </summary>\n        internal static string Cluster_Notification_SVD_Last {\n            get {\n                return ResourceManager.GetString(\"Cluster.Notification.SVD.Last\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Window 【{0}】 match rule 【{1}】, but error occur when moving.\n        ///possible reason:\n        ///- window invalid.\n        ///- target desktop not exists.\n        ///- target desktop invalid. 的本地化字符串。\n        /// </summary>\n        internal static string Error_MoveWindowToDesktop {\n            get {\n                return ResourceManager.GetString(\"Error.MoveWindowToDesktop\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Error! 的本地化字符串。\n        /// </summary>\n        internal static string Error_Title {\n            get {\n                return ResourceManager.GetString(\"Error.Title\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Cannot access task with your current permissions level.\n        ///You need to run this application &apos;as administrator&apos; even if you are using an administrator account. 的本地化字符串。\n        /// </summary>\n        internal static string General_RunOnStartup_Error_Permission {\n            get {\n                return ResourceManager.GetString(\"General.RunOnStartup.Error.Permission\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Down 的本地化字符串。\n        /// </summary>\n        internal static string hk_node_nav_down {\n            get {\n                return ResourceManager.GetString(\"hk_node_nav_down\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Left 的本地化字符串。\n        /// </summary>\n        internal static string hk_node_nav_left {\n            get {\n                return ResourceManager.GetString(\"hk_node_nav_left\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Right 的本地化字符串。\n        /// </summary>\n        internal static string hk_node_nav_right {\n            get {\n                return ResourceManager.GetString(\"hk_node_nav_right\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Up 的本地化字符串。\n        /// </summary>\n        internal static string hk_node_nav_up {\n            get {\n                return ResourceManager.GetString(\"hk_node_nav_up\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Open AppController 的本地化字符串。\n        /// </summary>\n        internal static string hk_node_open_app_controller {\n            get {\n                return ResourceManager.GetString(\"hk_node_open_app_controller\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Rise MainView 的本地化字符串。\n        /// </summary>\n        internal static string hk_node_rise_mainview {\n            get {\n                return ResourceManager.GetString(\"hk_node_rise_mainview\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Rise MainView For Active App 的本地化字符串。\n        /// </summary>\n        internal static string hk_node_rise_mainview_for_active_app {\n            get {\n                return ResourceManager.GetString(\"hk_node_rise_mainview_for_active_app\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Rise MainView For Active App In Current Desktop 的本地化字符串。\n        /// </summary>\n        internal static string hk_node_rise_mainview_for_active_app_in_current_vd {\n            get {\n                return ResourceManager.GetString(\"hk_node_rise_mainview_for_active_app_in_current_vd\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Rise MainView For Current Desktop 的本地化字符串。\n        /// </summary>\n        internal static string hk_node_rise_mainview_for_current_vd {\n            get {\n                return ResourceManager.GetString(\"hk_node_rise_mainview_for_current_vd\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Toggle Window Filter 的本地化字符串。\n        /// </summary>\n        internal static string hk_node_toggle_window_filter {\n            get {\n                return ResourceManager.GetString(\"hk_node_toggle_window_filter\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Desktop 的本地化字符串。\n        /// </summary>\n        internal static string K_D {\n            get {\n                return ResourceManager.GetString(\"K_D\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Navigation 的本地化字符串。\n        /// </summary>\n        internal static string K_D_N {\n            get {\n                return ResourceManager.GetString(\"K_D_N\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Switch 的本地化字符串。\n        /// </summary>\n        internal static string K_D_S {\n            get {\n                return ResourceManager.GetString(\"K_D_S\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 General 的本地化字符串。\n        /// </summary>\n        internal static string K_G {\n            get {\n                return ResourceManager.GetString(\"K_G\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Window 的本地化字符串。\n        /// </summary>\n        internal static string K_W {\n            get {\n                return ResourceManager.GetString(\"K_W\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Move 的本地化字符串。\n        /// </summary>\n        internal static string K_W_M {\n            get {\n                return ResourceManager.GetString(\"K_W_M\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Move and Follow 的本地化字符串。\n        /// </summary>\n        internal static string K_W_MF {\n            get {\n                return ResourceManager.GetString(\"K_W_MF\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Hotkey Cleared. 的本地化字符串。\n        /// </summary>\n        internal static string KB_Hotkey_Cleared {\n            get {\n                return ResourceManager.GetString(\"KB.Hotkey.Cleared\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Must choose a none-modifier Key. 的本地化字符串。\n        /// </summary>\n        internal static string KB_Hotkey_KeyCheck {\n            get {\n                return ResourceManager.GetString(\"KB.Hotkey.KeyCheck\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 At least one modifier Key. 的本地化字符串。\n        /// </summary>\n        internal static string KB_Hotkey_MKeyCheck {\n            get {\n                return ResourceManager.GetString(\"KB.Hotkey.MKeyCheck\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Move To Desktop  的本地化字符串。\n        /// </summary>\n        internal static string KB_Hotkey_MW {\n            get {\n                return ResourceManager.GetString(\"KB.Hotkey.MW\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Move and Follow To Desktop  的本地化字符串。\n        /// </summary>\n        internal static string KB_Hotkey_MWF {\n            get {\n                return ResourceManager.GetString(\"KB.Hotkey.MWF\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Register new Hotkey Failed. 的本地化字符串。\n        /// </summary>\n        internal static string KB_Hotkey_Reg_Fail {\n            get {\n                return ResourceManager.GetString(\"KB.Hotkey.Reg.Fail\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Register new Hotkey Success. 的本地化字符串。\n        /// </summary>\n        internal static string KB_Hotkey_Reg_Success {\n            get {\n                return ResourceManager.GetString(\"KB.Hotkey.Reg.Success\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Settings Saved. 的本地化字符串。\n        /// </summary>\n        internal static string KB_Hotkey_SettingsSaved {\n            get {\n                return ResourceManager.GetString(\"KB.Hotkey.SettingsSaved\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Switch To Desktop  的本地化字符串。\n        /// </summary>\n        internal static string KB_Hotkey_SVD {\n            get {\n                return ResourceManager.GetString(\"KB.Hotkey.SVD\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Switch Back To Last Desktop 的本地化字符串。\n        /// </summary>\n        internal static string KB_Hotkey_SVD_BACK_LAST {\n            get {\n                return ResourceManager.GetString(\"KB.Hotkey.SVD_BACK_LAST\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Left 的本地化字符串。\n        /// </summary>\n        internal static string Keys_Left {\n            get {\n                return ResourceManager.GetString(\"Keys.Left\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Middle 的本地化字符串。\n        /// </summary>\n        internal static string Keys_Middle {\n            get {\n                return ResourceManager.GetString(\"Keys.Middle\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Right 的本地化字符串。\n        /// </summary>\n        internal static string Keys_Right {\n            get {\n                return ResourceManager.GetString(\"Keys.Right\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Show ContextMenu 的本地化字符串。\n        /// </summary>\n        internal static string M_ContextMenu {\n            get {\n                return ResourceManager.GetString(\"M.ContextMenu\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Desktop 的本地化字符串。\n        /// </summary>\n        internal static string M_D {\n            get {\n                return ResourceManager.GetString(\"M.D\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Show Only Selected Desktop in View 的本地化字符串。\n        /// </summary>\n        internal static string M_D_DesktopShowForSelectedDesktop {\n            get {\n                return ResourceManager.GetString(\"M.D.DesktopShowForSelectedDesktop\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Switch Desktop and Close View 的本地化字符串。\n        /// </summary>\n        internal static string M_D_DesktopVisibleAndCloseView {\n            get {\n                return ResourceManager.GetString(\"M.D.DesktopVisibleAndCloseView\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Switch Desktop Only 的本地化字符串。\n        /// </summary>\n        internal static string M_D_DesktopVisibleOnly {\n            get {\n                return ResourceManager.GetString(\"M.D.DesktopVisibleOnly\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 MainView 的本地化字符串。\n        /// </summary>\n        internal static string M_ROOT {\n            get {\n                return ResourceManager.GetString(\"M.ROOT\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Window 的本地化字符串。\n        /// </summary>\n        internal static string M_W {\n            get {\n                return ResourceManager.GetString(\"M.W\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Active Window, Switch Desktop and Close View 的本地化字符串。\n        /// </summary>\n        internal static string M_W_WindowActiveDesktopVisibleAndCloseView {\n            get {\n                return ResourceManager.GetString(\"M.W.WindowActiveDesktopVisibleAndCloseView\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Active Window, Switch Desktop Only 的本地化字符串。\n        /// </summary>\n        internal static string M_W_WindowActiveDesktopVisibleOnly {\n            get {\n                return ResourceManager.GetString(\"M.W.WindowActiveDesktopVisibleOnly\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Close Window 的本地化字符串。\n        /// </summary>\n        internal static string M_W_WindowClose {\n            get {\n                return ResourceManager.GetString(\"M.W.WindowClose\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Hide From View 的本地化字符串。\n        /// </summary>\n        internal static string M_W_WindowHideFromView {\n            get {\n                return ResourceManager.GetString(\"M.W.WindowHideFromView\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Show Windows Only From Selected App in Selected Desktop 的本地化字符串。\n        /// </summary>\n        internal static string M_W_WindowShowForSelectedProcessInSelectedDesktop {\n            get {\n                return ResourceManager.GetString(\"M.W.WindowShowForSelectedProcessInSelectedDesktop\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Show Windows Only From Selected App 的本地化字符串。\n        /// </summary>\n        internal static string M_W_WindowShowForSelectedProcessOnly {\n            get {\n                return ResourceManager.GetString(\"M.W.WindowShowForSelectedProcessOnly\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Show Context Menu 的本地化字符串。\n        /// </summary>\n        internal static string Mouse_Action_ContextMenu {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.ContextMenu\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Show Only Selected Desktop in MainView 的本地化字符串。\n        /// </summary>\n        internal static string Mouse_Action_DesktopShowForSelectedDesktop {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.DesktopShowForSelectedDesktop\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Switch Desktop And Close View 的本地化字符串。\n        /// </summary>\n        internal static string Mouse_Action_DesktopVisibleAndCloseView {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.DesktopVisibleAndCloseView\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Switch Desktop Only 的本地化字符串。\n        /// </summary>\n        internal static string Mouse_Action_DesktopVisibleOnly {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.DesktopVisibleOnly\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Do Nothing 的本地化字符串。\n        /// </summary>\n        internal static string Mouse_Action_DoNothing {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.DoNothing\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Active Window, Switch Virtual Desktop And Close View 的本地化字符串。\n        /// </summary>\n        internal static string Mouse_Action_WindowActiveDesktopVisibleAndCloseView {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.WindowActiveDesktopVisibleAndCloseView\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Active Window, Switch Virtual Desktop Only 的本地化字符串。\n        /// </summary>\n        internal static string Mouse_Action_WindowActiveDesktopVisibleOnly {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.WindowActiveDesktopVisibleOnly\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Close Window 的本地化字符串。\n        /// </summary>\n        internal static string Mouse_Action_WindowClose {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.WindowClose\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Show Windows Only From Selected App in Selected Desktop 的本地化字符串。\n        /// </summary>\n        internal static string Mouse_Action_WindowShowForSelectedProcessInSelectedDesktop {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.WindowShowForSelectedProcessInSelectedDesktop\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Show Windows Only From Selected App 的本地化字符串。\n        /// </summary>\n        internal static string Mouse_Action_WindowShowForSelectedProcessOnly {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.WindowShowForSelectedProcessOnly\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 MouseAction Exists, try another combine or Mousebutton 的本地化字符串。\n        /// </summary>\n        internal static string Mouse_Tips_Exists {\n            get {\n                return ResourceManager.GetString(\"Mouse.Tips.Exists\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Confirm 的本地化字符串。\n        /// </summary>\n        internal static string MsgBox_Caption_Confirm {\n            get {\n                return ResourceManager.GetString(\"MsgBox.Caption.Confirm\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Warning 的本地化字符串。\n        /// </summary>\n        internal static string MsgBox_Caption_Warning {\n            get {\n                return ResourceManager.GetString(\"MsgBox.Caption.Warning\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Next row 的本地化字符串。\n        /// </summary>\n        internal static string Nav_CircleHType_NextRow {\n            get {\n                return ResourceManager.GetString(\"Nav.CircleHType.NextRow\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Same row 的本地化字符串。\n        /// </summary>\n        internal static string Nav_CircleHType_SameRow {\n            get {\n                return ResourceManager.GetString(\"Nav.CircleHType.SameRow\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Are you sure to delete this profile?\n        ///All files related with this profile will be deleted too. 的本地化字符串。\n        /// </summary>\n        internal static string Profile_Confirm_Delete {\n            get {\n                return ResourceManager.GetString(\"Profile.Confirm.Delete\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Invalid profile name, or profile name already exists. 的本地化字符串。\n        /// </summary>\n        internal static string Profile_Warning_InvalidProfileName {\n            get {\n                return ResourceManager.GetString(\"Profile.Warning.InvalidProfileName\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Can not rename or delete the last profile.\n        ///Duplicate one and edit it. 的本地化字符串。\n        /// </summary>\n        internal static string Profile_Warning_LastProfileProtect {\n            get {\n                return ResourceManager.GetString(\"Profile.Warning.LastProfileProtect\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 At least one common rule is required. 的本地化字符串。\n        /// </summary>\n        internal static string Rule_AtLeastOne {\n            get {\n                return ResourceManager.GetString(\"Rule.AtLeastOne\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Invalid Regex. 的本地化字符串。\n        /// </summary>\n        internal static string Rule_InvalidRegex {\n            get {\n                return ResourceManager.GetString(\"Rule.InvalidRegex\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 is required. 的本地化字符串。\n        /// </summary>\n        internal static string Rule_NameRequired {\n            get {\n                return ResourceManager.GetString(\"Rule.NameRequired\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 New Rule 的本地化字符串。\n        /// </summary>\n        internal static string Rule_New {\n            get {\n                return ResourceManager.GetString(\"Rule.New\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 is 的本地化字符串。\n        /// </summary>\n        internal static string Rule_Op_Eq {\n            get {\n                return ResourceManager.GetString(\"Rule.Op.Eq\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 ends with 的本地化字符串。\n        /// </summary>\n        internal static string Rule_Op_Esw {\n            get {\n                return ResourceManager.GetString(\"Rule.Op.Esw\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 regex 的本地化字符串。\n        /// </summary>\n        internal static string Rule_Op_Regex {\n            get {\n                return ResourceManager.GetString(\"Rule.Op.Regex\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 contains 的本地化字符串。\n        /// </summary>\n        internal static string Rule_Op_Sc {\n            get {\n                return ResourceManager.GetString(\"Rule.Op.Sc\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 starts with 的本地化字符串。\n        /// </summary>\n        internal static string Rule_Op_Ssw {\n            get {\n                return ResourceManager.GetString(\"Rule.Op.Ssw\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Quit 的本地化字符串。\n        /// </summary>\n        internal static string Tray_Menu_Quit {\n            get {\n                return ResourceManager.GetString(\"Tray.Menu.Quit\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Settings 的本地化字符串。\n        /// </summary>\n        internal static string Tray_Menu_Settings {\n            get {\n                return ResourceManager.GetString(\"Tray.Menu.Settings\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Mouse Button Required 的本地化字符串。\n        /// </summary>\n        internal static string Validation_Mouse_Button_Required {\n            get {\n                return ResourceManager.GetString(\"Validation.Mouse.Button.Required\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Create Virtual Desktop 的本地化字符串。\n        /// </summary>\n        internal static string VDW_CTM_Desktop_Create {\n            get {\n                return ResourceManager.GetString(\"VDW.CTM.Desktop.Create\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Remove Virtual Desktop 的本地化字符串。\n        /// </summary>\n        internal static string VDW_CTM_Desktop_Remove {\n            get {\n                return ResourceManager.GetString(\"VDW.CTM.Desktop.Remove\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Unhide Window 的本地化字符串。\n        /// </summary>\n        internal static string VDW_CTM_Desktop_UnHideWindow {\n            get {\n                return ResourceManager.GetString(\"VDW.CTM.Desktop.UnHideWindow\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Close 的本地化字符串。\n        /// </summary>\n        internal static string VDW_CTM_Window_Close {\n            get {\n                return ResourceManager.GetString(\"VDW.CTM.Window.Close\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Hide from view 的本地化字符串。\n        /// </summary>\n        internal static string VDW_CTM_Window_HideFromView {\n            get {\n                return ResourceManager.GetString(\"VDW.CTM.Window.HideFromView\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Create Rule from this Window... 的本地化字符串。\n        /// </summary>\n        internal static string VDW_CTM_Window_NewRule {\n            get {\n                return ResourceManager.GetString(\"VDW.CTM.Window.NewRule\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Show windows from this app on all desktops 的本地化字符串。\n        /// </summary>\n        internal static string VDW_CTM_Window_PinApp {\n            get {\n                return ResourceManager.GetString(\"VDW.CTM.Window.PinApp\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Show this window on all desktops 的本地化字符串。\n        /// </summary>\n        internal static string VDW_CTM_Window_PinWin {\n            get {\n                return ResourceManager.GetString(\"VDW.CTM.Window.PinWin\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Screen 的本地化字符串。\n        /// </summary>\n        internal static string VDW_CTM_Window_Screen {\n            get {\n                return ResourceManager.GetString(\"VDW.CTM.Window.Screen\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Unsupported Windows Version.\n        ///Application Will Quit.\n        ///\n        ///Support List\n        ///====================================\n        ///Windows 10 Redstone5(17763)\n        ///Windows 10 19H1(18362)\n        ///Windows 10 19H2(18363)\n        ///Windows 10 20H1(19041)\n        ///Windows 10 20H2(19042)\n        ///Windows 10 21H1(19043)\n        ///Windows 10 21H2(19044)\n        ///Windows 10 22H2(19045)\n        ///Windows 11 21H2(22000)\n        ///Windows 11 22H2(22621)\n        ///Windows 11 23H2(22631)\n        ///==================================== 的本地化字符串。\n        /// </summary>\n        internal static string VersionCheckFail {\n            get {\n                return ResourceManager.GetString(\"VersionCheckFail\", resourceCulture);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Bridge/Resources/Langs/WinFormStrings.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"VDW.CTM.Desktop.Create\" xml:space=\"preserve\">\n    <value>Create Virtual Desktop</value>\n  </data>\n  <data name=\"VDW.CTM.Desktop.Remove\" xml:space=\"preserve\">\n    <value>Remove Virtual Desktop</value>\n  </data>\n  <data name=\"VDW.CTM.Window.Close\" xml:space=\"preserve\">\n    <value>Close</value>\n  </data>\n  <data name=\"VDW.CTM.Window.PinApp\" xml:space=\"preserve\">\n    <value>Show windows from this app on all desktops</value>\n  </data>\n  <data name=\"VDW.CTM.Window.PinWin\" xml:space=\"preserve\">\n    <value>Show this window on all desktops</value>\n  </data>\n  <data name=\"VersionCheckFail\" xml:space=\"preserve\">\n    <value>Unsupported Windows Version.\nApplication Will Quit.\n\nSupport List\n====================================\nWindows 10 Redstone5(17763)\nWindows 10 19H1(18362)\nWindows 10 19H2(18363)\nWindows 10 20H1(19041)\nWindows 10 20H2(19042)\nWindows 10 21H1(19043)\nWindows 10 21H2(19044)\nWindows 10 22H2(19045)\nWindows 11 21H2(22000)\nWindows 11 22H2(22621)\nWindows 11 23H2(22631)\n====================================</value>\n  </data>\n  <data name=\"Rule.NameRequired\" xml:space=\"preserve\">\n    <value>is required.</value>\n  </data>\n  <data name=\"Rule.Op.Eq\" xml:space=\"preserve\">\n    <value>is</value>\n  </data>\n  <data name=\"Rule.Op.Ssw\" xml:space=\"preserve\">\n    <value>starts with</value>\n  </data>\n  <data name=\"Rule.Op.Esw\" xml:space=\"preserve\">\n    <value>ends with</value>\n  </data>\n  <data name=\"Rule.Op.Sc\" xml:space=\"preserve\">\n    <value>contains</value>\n  </data>\n  <data name=\"Rule.Op.Regex\" xml:space=\"preserve\">\n    <value>regex</value>\n  </data>\n  <data name=\"Rule.AtLeastOne\" xml:space=\"preserve\">\n    <value>At least one common rule is required.</value>\n  </data>\n  <data name=\"Rule.InvalidRegex\" xml:space=\"preserve\">\n    <value>Invalid Regex.</value>\n  </data>\n  <data name=\"VDW.CTM.Window.NewRule\" xml:space=\"preserve\">\n    <value>Create Rule from this Window...</value>\n  </data>\n  <data name=\"Rule.New\" xml:space=\"preserve\">\n    <value>New Rule</value>\n  </data>\n  <data name=\"Error.MoveWindowToDesktop\" xml:space=\"preserve\">\n    <value>Window 【{0}】 match rule 【{1}】, but error occur when moving.\npossible reason:\n- window invalid.\n- target desktop not exists.\n- target desktop invalid.</value>\n  </data>\n  <data name=\"Error.Title\" xml:space=\"preserve\">\n    <value>Error!</value>\n  </data>\n  <data name=\"VDW.CTM.Window.HideFromView\" xml:space=\"preserve\">\n    <value>Hide from view</value>\n  </data>\n  <data name=\"VDW.CTM.Desktop.UnHideWindow\" xml:space=\"preserve\">\n    <value>Unhide Window</value>\n  </data>\n  <data name=\"VDW.CTM.Window.Screen\" xml:space=\"preserve\">\n    <value>Screen</value>\n  </data>\n  <data name=\"Nav.CircleHType.NextRow\" xml:space=\"preserve\">\n    <value>Next row</value>\n  </data>\n  <data name=\"Nav.CircleHType.SameRow\" xml:space=\"preserve\">\n    <value>Same row</value>\n  </data>\n  <data name=\"KB.Hotkey.Cleared\" xml:space=\"preserve\">\n    <value>Hotkey Cleared.</value>\n  </data>\n  <data name=\"KB.Hotkey.Reg.Success\" xml:space=\"preserve\">\n    <value>Register new Hotkey Success.</value>\n  </data>\n  <data name=\"KB.Hotkey.Reg.Fail\" xml:space=\"preserve\">\n    <value>Register new Hotkey Failed.</value>\n  </data>\n  <data name=\"KB.Hotkey.SettingsSaved\" xml:space=\"preserve\">\n    <value>Settings Saved.</value>\n  </data>\n  <data name=\"KB.Hotkey.KeyCheck\" xml:space=\"preserve\">\n    <value>Must choose a none-modifier Key.</value>\n  </data>\n  <data name=\"Mouse.Action.DoNothing\" xml:space=\"preserve\">\n    <value>Do Nothing</value>\n  </data>\n  <data name=\"Mouse.Action.DesktopVisibleAndCloseView\" xml:space=\"preserve\">\n    <value>Switch Desktop And Close View</value>\n  </data>\n  <data name=\"Mouse.Action.DesktopVisibleOnly\" xml:space=\"preserve\">\n    <value>Switch Desktop Only</value>\n  </data>\n  <data name=\"Mouse.Action.ContextMenu\" xml:space=\"preserve\">\n    <value>Show Context Menu</value>\n  </data>\n  <data name=\"Mouse.Action.WindowActiveDesktopVisibleAndCloseView\" xml:space=\"preserve\">\n    <value>Active Window, Switch Virtual Desktop And Close View</value>\n  </data>\n  <data name=\"Mouse.Action.WindowActiveDesktopVisibleOnly\" xml:space=\"preserve\">\n    <value>Active Window, Switch Virtual Desktop Only</value>\n  </data>\n  <data name=\"Mouse.Action.WindowClose\" xml:space=\"preserve\">\n    <value>Close Window</value>\n  </data>\n  <data name=\"Cluster.Notification.SVD.Current\" xml:space=\"preserve\">\n    <value>Current Desktop: </value>\n  </data>\n  <data name=\"Cluster.Notification.SVD.Last\" xml:space=\"preserve\">\n    <value>Last Desktop: </value>\n  </data>\n  <data name=\"General.RunOnStartup.Error.Permission\" xml:space=\"preserve\">\n    <value>Cannot access task with your current permissions level.\nYou need to run this application 'as administrator' even if you are using an administrator account.</value>\n  </data>\n  <data name=\"Mouse.Action.WindowShowForSelectedProcessOnly\" xml:space=\"preserve\">\n    <value>Show Windows Only From Selected App</value>\n  </data>\n  <data name=\"KB.Hotkey.SVD\" xml:space=\"preserve\">\n    <value>Switch To Desktop </value>\n  </data>\n  <data name=\"KB.Hotkey.MW\" xml:space=\"preserve\">\n    <value>Move To Desktop </value>\n  </data>\n  <data name=\"KB.Hotkey.MWF\" xml:space=\"preserve\">\n    <value>Move and Follow To Desktop </value>\n  </data>\n  <data name=\"Mouse.Action.WindowShowForSelectedProcessInSelectedDesktop\" xml:space=\"preserve\">\n    <value>Show Windows Only From Selected App in Selected Desktop</value>\n  </data>\n  <data name=\"Keys.Left\" xml:space=\"preserve\">\n    <value>Left</value>\n  </data>\n  <data name=\"Keys.Middle\" xml:space=\"preserve\">\n    <value>Middle</value>\n  </data>\n  <data name=\"Keys.Right\" xml:space=\"preserve\">\n    <value>Right</value>\n  </data>\n  <data name=\"Mouse.Action.DesktopShowForSelectedDesktop\" xml:space=\"preserve\">\n    <value>Show Only Selected Desktop in MainView</value>\n  </data>\n  <data name=\"KB.Hotkey.SVD_BACK_LAST\" xml:space=\"preserve\">\n    <value>Switch Back To Last Desktop</value>\n  </data>\n  <data name=\"Profile.Confirm.Delete\" xml:space=\"preserve\">\n    <value>Are you sure to delete this profile?\nAll files related with this profile will be deleted too.</value>\n  </data>\n  <data name=\"Profile.Warning.LastProfileProtect\" xml:space=\"preserve\">\n    <value>Can not rename or delete the last profile.\nDuplicate one and edit it.</value>\n  </data>\n  <data name=\"Profile.Warning.InvalidProfileName\" xml:space=\"preserve\">\n    <value>Invalid profile name, or profile name already exists.</value>\n  </data>\n  <data name=\"MsgBox.Caption.Warning\" xml:space=\"preserve\">\n    <value>Warning</value>\n  </data>\n  <data name=\"MsgBox.Caption.Confirm\" xml:space=\"preserve\">\n    <value>Confirm</value>\n  </data>\n  <data name=\"Tray.Menu.Settings\" xml:space=\"preserve\">\n    <value>Settings</value>\n  </data>\n  <data name=\"Tray.Menu.Quit\" xml:space=\"preserve\">\n    <value>Quit</value>\n  </data>\n  <data name=\"K_G\" xml:space=\"preserve\">\n    <value>General</value>\n  </data>\n  <data name=\"hk_node_rise_mainview\" xml:space=\"preserve\">\n    <value>Rise MainView</value>\n  </data>\n  <data name=\"hk_node_open_app_controller\" xml:space=\"preserve\">\n    <value>Open AppController</value>\n  </data>\n  <data name=\"hk_node_rise_mainview_for_active_app\" xml:space=\"preserve\">\n    <value>Rise MainView For Active App</value>\n  </data>\n  <data name=\"hk_node_rise_mainview_for_current_vd\" xml:space=\"preserve\">\n    <value>Rise MainView For Current Desktop</value>\n  </data>\n  <data name=\"hk_node_rise_mainview_for_active_app_in_current_vd\" xml:space=\"preserve\">\n    <value>Rise MainView For Active App In Current Desktop</value>\n  </data>\n  <data name=\"K_D\" xml:space=\"preserve\">\n    <value>Desktop</value>\n  </data>\n  <data name=\"K_D_S\" xml:space=\"preserve\">\n    <value>Switch</value>\n  </data>\n  <data name=\"K_D_N\" xml:space=\"preserve\">\n    <value>Navigation</value>\n  </data>\n  <data name=\"K_W\" xml:space=\"preserve\">\n    <value>Window</value>\n  </data>\n  <data name=\"K_W_M\" xml:space=\"preserve\">\n    <value>Move</value>\n  </data>\n  <data name=\"K_W_MF\" xml:space=\"preserve\">\n    <value>Move and Follow</value>\n  </data>\n  <data name=\"hk_node_nav_right\" xml:space=\"preserve\">\n    <value>Right</value>\n  </data>\n  <data name=\"hk_node_nav_up\" xml:space=\"preserve\">\n    <value>Up</value>\n  </data>\n  <data name=\"hk_node_nav_down\" xml:space=\"preserve\">\n    <value>Down</value>\n  </data>\n  <data name=\"hk_node_nav_left\" xml:space=\"preserve\">\n    <value>Left</value>\n  </data>\n  <data name=\"KB.Hotkey.MKeyCheck\" xml:space=\"preserve\">\n    <value>At least one modifier Key.</value>\n  </data>\n  <data name=\"M.D\" xml:space=\"preserve\">\n    <value>Desktop</value>\n  </data>\n  <data name=\"M.W\" xml:space=\"preserve\">\n    <value>Window</value>\n  </data>\n  <data name=\"M.ROOT\" xml:space=\"preserve\">\n    <value>MainView</value>\n  </data>\n  <data name=\"M.D.DesktopVisibleAndCloseView\" xml:space=\"preserve\">\n    <value>Switch Desktop and Close View</value>\n  </data>\n  <data name=\"M.D.DesktopVisibleOnly\" xml:space=\"preserve\">\n    <value>Switch Desktop Only</value>\n  </data>\n  <data name=\"M.ContextMenu\" xml:space=\"preserve\">\n    <value>Show ContextMenu</value>\n  </data>\n  <data name=\"M.D.DesktopShowForSelectedDesktop\" xml:space=\"preserve\">\n    <value>Show Only Selected Desktop in View</value>\n  </data>\n  <data name=\"M.W.WindowActiveDesktopVisibleAndCloseView\" xml:space=\"preserve\">\n    <value>Active Window, Switch Desktop and Close View</value>\n  </data>\n  <data name=\"M.W.WindowActiveDesktopVisibleOnly\" xml:space=\"preserve\">\n    <value>Active Window, Switch Desktop Only</value>\n  </data>\n  <data name=\"M.W.WindowHideFromView\" xml:space=\"preserve\">\n    <value>Hide From View</value>\n  </data>\n  <data name=\"M.W.WindowClose\" xml:space=\"preserve\">\n    <value>Close Window</value>\n  </data>\n  <data name=\"M.W.WindowShowForSelectedProcessOnly\" xml:space=\"preserve\">\n    <value>Show Windows Only From Selected App</value>\n  </data>\n  <data name=\"M.W.WindowShowForSelectedProcessInSelectedDesktop\" xml:space=\"preserve\">\n    <value>Show Windows Only From Selected App in Selected Desktop</value>\n  </data>\n  <data name=\"Validation.Mouse.Button.Required\" xml:space=\"preserve\">\n    <value>Mouse Button Required</value>\n  </data>\n  <data name=\"Mouse.Tips.Exists\" xml:space=\"preserve\">\n    <value>MouseAction Exists, try another combine or Mousebutton</value>\n  </data>\n  <data name=\"hk_node_toggle_window_filter\" xml:space=\"preserve\">\n    <value>Toggle Window Filter</value>\n  </data>\n</root>"
  },
  {
    "path": "Bridge/Resources/Langs/WinFormStrings.zh-Hans.Designer.cs",
    "content": "﻿//------------------------------------------------------------------------------\n// <auto-generated>\n//     This code was generated by a tool.\n//\n//     Changes to this file may cause incorrect behavior and will be lost if\n//     the code is regenerated.\n// </auto-generated>\n//------------------------------------------------------------------------------\n\nnamespace VirtualSpace.Resources.Langs {\n    using System;\n    \n    \n    /// <summary>\n    ///   A strongly-typed resource class, for looking up localized strings, etc.\n    /// </summary>\n    // This class was auto-generated by the StronglyTypedResourceBuilder\n    // class via a tool like ResGen or Visual Studio.\n    // To add or remove a member, edit your .ResX file then rerun ResGen\n    // with the /str option, or rebuild your VS project.\n    [global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Resources.Tools.StronglyTypedResourceBuilder\", \"17.0.0.0\")]\n    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]\n    internal class WinFormStrings_zh_Hans {\n        \n        private static global::System.Resources.ResourceManager resourceMan;\n        \n        private static global::System.Globalization.CultureInfo resourceCulture;\n        \n        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute(\"Microsoft.Performance\", \"CA1811:AvoidUncalledPrivateCode\")]\n        internal WinFormStrings_zh_Hans() {\n        }\n        \n        /// <summary>\n        ///   Returns the cached ResourceManager instance used by this class.\n        /// </summary>\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\n        internal static global::System.Resources.ResourceManager ResourceManager {\n            get {\n                if (object.ReferenceEquals(resourceMan, null)) {\n                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager(\"Bridge.Resources.Langs.WinFormStrings.zh-Hans\", typeof(WinFormStrings_zh_Hans).Assembly);\n                    resourceMan = temp;\n                }\n                return resourceMan;\n            }\n        }\n        \n        /// <summary>\n        ///   Overrides the current thread's CurrentUICulture property for all\n        ///   resource lookups using this strongly typed resource class.\n        /// </summary>\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\n        internal static global::System.Globalization.CultureInfo Culture {\n            get {\n                return resourceCulture;\n            }\n            set {\n                resourceCulture = value;\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 当前桌面：.\n        /// </summary>\n        internal static string Cluster_Notification_SVD_Current {\n            get {\n                return ResourceManager.GetString(\"Cluster.Notification.SVD.Current\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 上一个桌面：.\n        /// </summary>\n        internal static string Cluster_Notification_SVD_Last {\n            get {\n                return ResourceManager.GetString(\"Cluster.Notification.SVD.Last\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 窗口 【{0}】 匹配规则 【{1}】，但移动时发生错误。\n        ///可能的原因：\n        ///- 窗口无效。\n        ///- 目标桌面不存在。\n        ///- 目标桌面无效。.\n        /// </summary>\n        internal static string Error_MoveWindowToDesktop {\n            get {\n                return ResourceManager.GetString(\"Error.MoveWindowToDesktop\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 错误！.\n        /// </summary>\n        internal static string Error_Title {\n            get {\n                return ResourceManager.GetString(\"Error.Title\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 当前权限级别无法访问计划任务，\n        ///请确保当前账户是此计算机的管理员并且“以管理员身份运行”运行此程序。.\n        /// </summary>\n        internal static string General_RunOnStartup_Error_Permission {\n            get {\n                return ResourceManager.GetString(\"General.RunOnStartup.Error.Permission\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 桌面.\n        /// </summary>\n        internal static string K_D {\n            get {\n                return ResourceManager.GetString(\"K.D\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 导航.\n        /// </summary>\n        internal static string K_D_N {\n            get {\n                return ResourceManager.GetString(\"K.D.N\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 向左.\n        /// </summary>\n        internal static string K_D_N_D {\n            get {\n                return ResourceManager.GetString(\"K.D.N.D\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 向右.\n        /// </summary>\n        internal static string K_D_N_L {\n            get {\n                return ResourceManager.GetString(\"K.D.N.L\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 向上.\n        /// </summary>\n        internal static string K_D_N_R {\n            get {\n                return ResourceManager.GetString(\"K.D.N.R\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 向下.\n        /// </summary>\n        internal static string K_D_N_U {\n            get {\n                return ResourceManager.GetString(\"K.D.N.U\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 切换桌面.\n        /// </summary>\n        internal static string K_D_S {\n            get {\n                return ResourceManager.GetString(\"K.D.S\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 通用.\n        /// </summary>\n        internal static string K_G {\n            get {\n                return ResourceManager.GetString(\"K.G\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 打开程序控制.\n        /// </summary>\n        internal static string K_G_oac {\n            get {\n                return ResourceManager.GetString(\"K.G.oac\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 唤起主视图.\n        /// </summary>\n        internal static string K_G_rmv {\n            get {\n                return ResourceManager.GetString(\"K.G.rmv\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 为当前活动程序唤起主视图.\n        /// </summary>\n        internal static string K_G_rmvfaa {\n            get {\n                return ResourceManager.GetString(\"K.G.rmvfaa\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 为当前桌面中的活动程序唤起主视图.\n        /// </summary>\n        internal static string K_G_rmvfaaicvd {\n            get {\n                return ResourceManager.GetString(\"K.G.rmvfaaicvd\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 为当前桌面唤起主视图.\n        /// </summary>\n        internal static string K_G_rmvfcd {\n            get {\n                return ResourceManager.GetString(\"K.G.rmvfcd\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 窗口.\n        /// </summary>\n        internal static string K_W {\n            get {\n                return ResourceManager.GetString(\"K.W\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 移动.\n        /// </summary>\n        internal static string K_W_M {\n            get {\n                return ResourceManager.GetString(\"K.W.M\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 移动并跟随.\n        /// </summary>\n        internal static string K_W_MF {\n            get {\n                return ResourceManager.GetString(\"K.W.MF\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 热键已清除。.\n        /// </summary>\n        internal static string KB_Hotkey_Cleared {\n            get {\n                return ResourceManager.GetString(\"KB.Hotkey.Cleared\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 必须选择一个非修改类键。.\n        /// </summary>\n        internal static string KB_Hotkey_KeyCheck {\n            get {\n                return ResourceManager.GetString(\"KB.Hotkey.KeyCheck\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 移动到桌面 .\n        /// </summary>\n        internal static string KB_Hotkey_MW {\n            get {\n                return ResourceManager.GetString(\"KB.Hotkey.MW\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 移动并跟随到桌面 .\n        /// </summary>\n        internal static string KB_Hotkey_MWF {\n            get {\n                return ResourceManager.GetString(\"KB.Hotkey.MWF\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 热键注册失败。.\n        /// </summary>\n        internal static string KB_Hotkey_Reg_Fail {\n            get {\n                return ResourceManager.GetString(\"KB.Hotkey.Reg.Fail\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 热键注册成功。.\n        /// </summary>\n        internal static string KB_Hotkey_Reg_Success {\n            get {\n                return ResourceManager.GetString(\"KB.Hotkey.Reg.Success\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 设置已保存。.\n        /// </summary>\n        internal static string KB_Hotkey_SettingsSaved {\n            get {\n                return ResourceManager.GetString(\"KB.Hotkey.SettingsSaved\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 切换到桌面 .\n        /// </summary>\n        internal static string KB_Hotkey_SVD {\n            get {\n                return ResourceManager.GetString(\"KB.Hotkey.SVD\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 切换回上一个桌面.\n        /// </summary>\n        internal static string KB_Hotkey_SVD_BACK_LAST {\n            get {\n                return ResourceManager.GetString(\"KB.Hotkey.SVD_BACK_LAST\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 左键.\n        /// </summary>\n        internal static string Keys_Left {\n            get {\n                return ResourceManager.GetString(\"Keys.Left\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 中键.\n        /// </summary>\n        internal static string Keys_Middle {\n            get {\n                return ResourceManager.GetString(\"Keys.Middle\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 右键.\n        /// </summary>\n        internal static string Keys_Right {\n            get {\n                return ResourceManager.GetString(\"Keys.Right\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 显示上下文菜单.\n        /// </summary>\n        internal static string Mouse_Action_ContextMenu {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.ContextMenu\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 仅显示所选桌面.\n        /// </summary>\n        internal static string Mouse_Action_DesktopShowForSelectedDesktop {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.DesktopShowForSelectedDesktop\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 切换虚拟桌面并关闭视图.\n        /// </summary>\n        internal static string Mouse_Action_DesktopVisibleAndCloseView {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.DesktopVisibleAndCloseView\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 仅切换虚拟桌面.\n        /// </summary>\n        internal static string Mouse_Action_DesktopVisibleOnly {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.DesktopVisibleOnly\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 什么都不做.\n        /// </summary>\n        internal static string Mouse_Action_DoNothing {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.DoNothing\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 激活窗口，切换桌面并关闭视图.\n        /// </summary>\n        internal static string Mouse_Action_WindowActiveDesktopVisibleAndCloseView {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.WindowActiveDesktopVisibleAndCloseView\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 激活窗口，切换桌面.\n        /// </summary>\n        internal static string Mouse_Action_WindowActiveDesktopVisibleOnly {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.WindowActiveDesktopVisibleOnly\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 关闭窗口.\n        /// </summary>\n        internal static string Mouse_Action_WindowClose {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.WindowClose\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 仅显示所选桌面中的活动程序窗口.\n        /// </summary>\n        internal static string Mouse_Action_WindowShowForSelectedProcessInSelectedDesktop {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.WindowShowForSelectedProcessInSelectedDesktop\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 仅显示此程序的窗口.\n        /// </summary>\n        internal static string Mouse_Action_WindowShowForSelectedProcessOnly {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.WindowShowForSelectedProcessOnly\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 确认.\n        /// </summary>\n        internal static string MsgBox_Caption_Confirm {\n            get {\n                return ResourceManager.GetString(\"MsgBox.Caption.Confirm\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 警告.\n        /// </summary>\n        internal static string MsgBox_Caption_Warning {\n            get {\n                return ResourceManager.GetString(\"MsgBox.Caption.Warning\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 切换到下一行.\n        /// </summary>\n        internal static string Nav_CircleHType_NextRow {\n            get {\n                return ResourceManager.GetString(\"Nav.CircleHType.NextRow\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 在同一行内循环.\n        /// </summary>\n        internal static string Nav_CircleHType_SameRow {\n            get {\n                return ResourceManager.GetString(\"Nav.CircleHType.SameRow\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 确定要删除这个配置文件吗？\n        ///所有与此配置文件相关的文件都将被删除。.\n        /// </summary>\n        internal static string Profile_Confirm_Delete {\n            get {\n                return ResourceManager.GetString(\"Profile.Confirm.Delete\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 配置文件名无效，或该文件已存在。.\n        /// </summary>\n        internal static string Profile_Warning_InvalidProfileName {\n            get {\n                return ResourceManager.GetString(\"Profile.Warning.InvalidProfileName\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 不能重命名或删除最后一个配置文件。.\n        /// </summary>\n        internal static string Profile_Warning_LastProfileProtect {\n            get {\n                return ResourceManager.GetString(\"Profile.Warning.LastProfileProtect\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 至少需要一条窗口规则。.\n        /// </summary>\n        internal static string Rule_AtLeastOne {\n            get {\n                return ResourceManager.GetString(\"Rule.AtLeastOne\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 无效的正则表达式。.\n        /// </summary>\n        internal static string Rule_InvalidRegex {\n            get {\n                return ResourceManager.GetString(\"Rule.InvalidRegex\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 是必须的。.\n        /// </summary>\n        internal static string Rule_NameRequired {\n            get {\n                return ResourceManager.GetString(\"Rule.NameRequired\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 新规则.\n        /// </summary>\n        internal static string Rule_New {\n            get {\n                return ResourceManager.GetString(\"Rule.New\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 是.\n        /// </summary>\n        internal static string Rule_Op_Eq {\n            get {\n                return ResourceManager.GetString(\"Rule.Op.Eq\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 以...结尾.\n        /// </summary>\n        internal static string Rule_Op_Esw {\n            get {\n                return ResourceManager.GetString(\"Rule.Op.Esw\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 正则表达式.\n        /// </summary>\n        internal static string Rule_Op_Regex {\n            get {\n                return ResourceManager.GetString(\"Rule.Op.Regex\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 包含.\n        /// </summary>\n        internal static string Rule_Op_Sc {\n            get {\n                return ResourceManager.GetString(\"Rule.Op.Sc\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 以...开头.\n        /// </summary>\n        internal static string Rule_Op_Ssw {\n            get {\n                return ResourceManager.GetString(\"Rule.Op.Ssw\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 退出.\n        /// </summary>\n        internal static string Tray_Menu_Quit {\n            get {\n                return ResourceManager.GetString(\"Tray.Menu.Quit\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 设置.\n        /// </summary>\n        internal static string Tray_Menu_Settings {\n            get {\n                return ResourceManager.GetString(\"Tray.Menu.Settings\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 创建新的虚拟桌面.\n        /// </summary>\n        internal static string VDW_CTM_Desktop_Create {\n            get {\n                return ResourceManager.GetString(\"VDW.CTM.Desktop.Create\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 删除虚拟桌面.\n        /// </summary>\n        internal static string VDW_CTM_Desktop_Remove {\n            get {\n                return ResourceManager.GetString(\"VDW.CTM.Desktop.Remove\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 取消隐藏窗口.\n        /// </summary>\n        internal static string VDW_CTM_Desktop_UnHideWindow {\n            get {\n                return ResourceManager.GetString(\"VDW.CTM.Desktop.UnHideWindow\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 关闭.\n        /// </summary>\n        internal static string VDW_CTM_Window_Close {\n            get {\n                return ResourceManager.GetString(\"VDW.CTM.Window.Close\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 从视图中隐藏.\n        /// </summary>\n        internal static string VDW_CTM_Window_HideFromView {\n            get {\n                return ResourceManager.GetString(\"VDW.CTM.Window.HideFromView\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 为此窗口创建规则....\n        /// </summary>\n        internal static string VDW_CTM_Window_NewRule {\n            get {\n                return ResourceManager.GetString(\"VDW.CTM.Window.NewRule\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 在所有桌面上显示此应用的窗口.\n        /// </summary>\n        internal static string VDW_CTM_Window_PinApp {\n            get {\n                return ResourceManager.GetString(\"VDW.CTM.Window.PinApp\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 在所有桌面上显示此窗口.\n        /// </summary>\n        internal static string VDW_CTM_Window_PinWin {\n            get {\n                return ResourceManager.GetString(\"VDW.CTM.Window.PinWin\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 屏幕.\n        /// </summary>\n        internal static string VDW_CTM_Window_Screen {\n            get {\n                return ResourceManager.GetString(\"VDW.CTM.Window.Screen\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 不支持的 Windows 版本\n        ///应用程序将退出\n        ///\n        ///支持的列表\n        ///====================================\n        ///Windows 10\tRedstone5(17763)\n        ///Windows 10\t19H1(18362)\n        ///Windows 10\t19H2(18363)\n        ///Windows 10\t20H1(19041)\n        ///Windows 10\t20H2(19042)\n        ///Windows 10\t21H1(19043)\n        ///Windows 10\t21H2(19044)\n        ///Windows 10\t22H2(19045)\n        ///Windows 11\t21H2(22000)\n        ///Windows 11\t22H2(22621)\n        ///====================================.\n        /// </summary>\n        internal static string VersionCheckFail {\n            get {\n                return ResourceManager.GetString(\"VersionCheckFail\", resourceCulture);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Bridge/Resources/Langs/WinFormStrings.zh-Hans.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"VDW.CTM.Desktop.Create\" xml:space=\"preserve\">\n    <value>创建新的虚拟桌面</value>\n  </data>\n  <data name=\"VDW.CTM.Desktop.Remove\" xml:space=\"preserve\">\n    <value>删除虚拟桌面</value>\n  </data>\n  <data name=\"VDW.CTM.Window.Close\" xml:space=\"preserve\">\n    <value>关闭</value>\n  </data>\n  <data name=\"VDW.CTM.Window.PinApp\" xml:space=\"preserve\">\n    <value>在所有桌面上显示此应用的窗口</value>\n  </data>\n  <data name=\"VDW.CTM.Window.PinWin\" xml:space=\"preserve\">\n    <value>在所有桌面上显示此窗口</value>\n  </data>\n  <data name=\"VersionCheckFail\" xml:space=\"preserve\">\n    <value>不支持的 Windows 版本\n应用程序将退出\n\n支持的列表\n====================================\nWindows 10 Redstone5(17763)\nWindows 10 19H1(18362)\nWindows 10 19H2(18363)\nWindows 10 20H1(19041)\nWindows 10 20H2(19042)\nWindows 10 21H1(19043)\nWindows 10 21H2(19044)\nWindows 10 22H2(19045)\nWindows 11 21H2(22000)\nWindows 11 22H2(22621)\nWindows 11 23H2(22631)\n====================================</value>\n  </data>\n  <data name=\"Rule.Op.Eq\" xml:space=\"preserve\">\n    <value>是</value>\n  </data>\n  <data name=\"Rule.Op.Ssw\" xml:space=\"preserve\">\n    <value>以...开头</value>\n  </data>\n  <data name=\"Rule.Op.Esw\" xml:space=\"preserve\">\n    <value>以...结尾</value>\n  </data>\n  <data name=\"Rule.Op.Sc\" xml:space=\"preserve\">\n    <value>包含</value>\n  </data>\n  <data name=\"Rule.Op.Regex\" xml:space=\"preserve\">\n    <value>正则表达式</value>\n  </data>\n  <data name=\"Rule.AtLeastOne\" xml:space=\"preserve\">\n    <value>至少需要一条窗口规则。</value>\n  </data>\n  <data name=\"Rule.InvalidRegex\" xml:space=\"preserve\">\n    <value>无效的正则表达式。</value>\n  </data>\n  <data name=\"Rule.NameRequired\" xml:space=\"preserve\">\n    <value>是必须的。</value>\n  </data>\n  <data name=\"VDW.CTM.Window.NewRule\" xml:space=\"preserve\">\n    <value>为此窗口创建规则...</value>\n  </data>\n  <data name=\"Rule.New\" xml:space=\"preserve\">\n    <value>新规则</value>\n  </data>\n  <data name=\"Error.MoveWindowToDesktop\" xml:space=\"preserve\">\n    <value>窗口 【{0}】 匹配规则 【{1}】，但移动时发生错误。\n可能的原因：\n- 窗口无效。\n- 目标桌面不存在。\n- 目标桌面无效。</value>\n  </data>\n  <data name=\"Error.Title\" xml:space=\"preserve\">\n    <value>错误！</value>\n  </data>\n  <data name=\"VDW.CTM.Window.HideFromView\" xml:space=\"preserve\">\n    <value>从视图中隐藏</value>\n  </data>\n  <data name=\"VDW.CTM.Desktop.UnHideWindow\" xml:space=\"preserve\">\n    <value>取消隐藏窗口</value>\n  </data>\n  <data name=\"VDW.CTM.Window.Screen\" xml:space=\"preserve\">\n    <value>屏幕</value>\n  </data>\n  <data name=\"Nav.CircleHType.NextRow\" xml:space=\"preserve\">\n    <value>切换到下一行</value>\n  </data>\n  <data name=\"Nav.CircleHType.SameRow\" xml:space=\"preserve\">\n    <value>在同一行内循环</value>\n  </data>\n  <data name=\"KB.Hotkey.Cleared\" xml:space=\"preserve\">\n    <value>热键已清除。</value>\n  </data>\n  <data name=\"KB.Hotkey.Reg.Success\" xml:space=\"preserve\">\n    <value>热键注册成功。</value>\n  </data>\n  <data name=\"KB.Hotkey.Reg.Fail\" xml:space=\"preserve\">\n    <value>热键注册失败。</value>\n  </data>\n  <data name=\"KB.Hotkey.SettingsSaved\" xml:space=\"preserve\">\n    <value>设置已保存。</value>\n  </data>\n  <data name=\"KB.Hotkey.KeyCheck\" xml:space=\"preserve\">\n    <value>必须选择一个非修改类键。</value>\n  </data>\n  <data name=\"Mouse.Action.DoNothing\" xml:space=\"preserve\">\n    <value>什么都不做</value>\n  </data>\n  <data name=\"Mouse.Action.DesktopVisibleOnly\" xml:space=\"preserve\">\n    <value>仅切换桌面</value>\n  </data>\n  <data name=\"Mouse.Action.DesktopVisibleAndCloseView\" xml:space=\"preserve\">\n    <value>切换桌面并关闭视图</value>\n  </data>\n  <data name=\"Mouse.Action.ContextMenu\" xml:space=\"preserve\">\n    <value>显示上下文菜单</value>\n  </data>\n  <data name=\"Mouse.Action.WindowClose\" xml:space=\"preserve\">\n    <value>关闭窗口</value>\n  </data>\n  <data name=\"Mouse.Action.WindowActiveDesktopVisibleAndCloseView\" xml:space=\"preserve\">\n    <value>激活窗口，切换桌面并关闭视图</value>\n  </data>\n  <data name=\"Mouse.Action.WindowActiveDesktopVisibleOnly\" xml:space=\"preserve\">\n    <value>激活窗口，切换桌面</value>\n  </data>\n  <data name=\"Cluster.Notification.SVD.Current\" xml:space=\"preserve\">\n    <value>当前桌面：</value>\n  </data>\n  <data name=\"Cluster.Notification.SVD.Last\" xml:space=\"preserve\">\n    <value>上一个桌面：</value>\n  </data>\n  <data name=\"General.RunOnStartup.Error.Permission\" xml:space=\"preserve\">\n    <value>当前权限级别无法访问计划任务，\n请确保当前账户是此计算机的管理员并且“以管理员身份运行”运行此程序。</value>\n  </data>\n  <data name=\"Mouse.Action.WindowShowForSelectedProcessOnly\" xml:space=\"preserve\">\n    <value>仅显示此程序的窗口</value>\n  </data>\n  <data name=\"KB.Hotkey.SVD\" xml:space=\"preserve\">\n    <value>切换到桌面 </value>\n  </data>\n  <data name=\"KB.Hotkey.MW\" xml:space=\"preserve\">\n    <value>移动到桌面 </value>\n  </data>\n  <data name=\"KB.Hotkey.MWF\" xml:space=\"preserve\">\n    <value>移动并跟随到桌面 </value>\n  </data>\n  <data name=\"Mouse.Action.WindowShowForSelectedProcessInSelectedDesktop\" xml:space=\"preserve\">\n    <value>仅显示所选桌面中的活动程序窗口</value>\n  </data>\n  <data name=\"Keys.Left\" xml:space=\"preserve\">\n    <value>左键</value>\n  </data>\n  <data name=\"Keys.Middle\" xml:space=\"preserve\">\n    <value>中键</value>\n  </data>\n  <data name=\"Keys.Right\" xml:space=\"preserve\">\n    <value>右键</value>\n  </data>\n  <data name=\"Mouse.Action.DesktopShowForSelectedDesktop\" xml:space=\"preserve\">\n    <value>仅显示所选桌面</value>\n  </data>\n  <data name=\"KB.Hotkey.SVD_BACK_LAST\" xml:space=\"preserve\">\n    <value>切换回上一个桌面</value>\n  </data>\n  <data name=\"Profile.Warning.LastProfileProtect\" xml:space=\"preserve\">\n    <value>不能重命名或删除最后一个配置文件。\n复制一个新的配置文件后即可操作。</value>\n  </data>\n  <data name=\"Profile.Confirm.Delete\" xml:space=\"preserve\">\n    <value>确定要删除这个配置文件吗？\n所有与此配置文件相关的文件都将被删除。</value>\n  </data>\n  <data name=\"Profile.Warning.InvalidProfileName\" xml:space=\"preserve\">\n    <value>配置文件名无效，或该文件已存在。</value>\n  </data>\n  <data name=\"MsgBox.Caption.Confirm\" xml:space=\"preserve\">\n    <value>确认</value>\n  </data>\n  <data name=\"MsgBox.Caption.Warning\" xml:space=\"preserve\">\n    <value>警告</value>\n  </data>\n  <data name=\"Tray.Menu.Settings\" xml:space=\"preserve\">\n    <value>设置</value>\n  </data>\n  <data name=\"Tray.Menu.Quit\" xml:space=\"preserve\">\n    <value>退出</value>\n  </data>\n  <data name=\"K_G\" xml:space=\"preserve\">\n    <value>通用</value>\n  </data>\n  <data name=\"hk_node_open_app_controller\" xml:space=\"preserve\">\n    <value>打开程序控制</value>\n  </data>\n  <data name=\"hk_node_rise_mainview\" xml:space=\"preserve\">\n    <value>唤起主视图</value>\n  </data>\n  <data name=\"hk_node_rise_mainview_for_active_app\" xml:space=\"preserve\">\n    <value>为当前活动程序唤起主视图</value>\n  </data>\n  <data name=\"hk_node_rise_mainview_for_current_vd\" xml:space=\"preserve\">\n    <value>为当前桌面唤起主视图</value>\n  </data>\n  <data name=\"hk_node_rise_mainview_for_active_app_in_current_vd\" xml:space=\"preserve\">\n    <value>为当前桌面中的活动程序唤起主视图</value>\n  </data>\n  <data name=\"K_D\" xml:space=\"preserve\">\n    <value>桌面</value>\n  </data>\n  <data name=\"K_D_N\" xml:space=\"preserve\">\n    <value>导航</value>\n  </data>\n  <data name=\"K_D_S\" xml:space=\"preserve\">\n    <value>切换桌面</value>\n  </data>\n  <data name=\"K_W\" xml:space=\"preserve\">\n    <value>窗口</value>\n  </data>\n  <data name=\"K_W_M\" xml:space=\"preserve\">\n    <value>移动</value>\n  </data>\n  <data name=\"K_W_MF\" xml:space=\"preserve\">\n    <value>移动并跟随</value>\n  </data>\n  <data name=\"hk_node_nav_left\" xml:space=\"preserve\">\n    <value>向左</value>\n  </data>\n  <data name=\"hk_node_nav_right\" xml:space=\"preserve\">\n    <value>向右</value>\n  </data>\n  <data name=\"hk_node_nav_up\" xml:space=\"preserve\">\n    <value>向上</value>\n  </data>\n  <data name=\"hk_node_nav_down\" xml:space=\"preserve\">\n    <value>向下</value>\n  </data>\n  <data name=\"KB.Hotkey.MKeyCheck\" xml:space=\"preserve\">\n    <value>至少需要一个修改类键。</value>\n  </data>\n  <data name=\"M.D\" xml:space=\"preserve\">\n    <value>桌面</value>\n  </data>\n  <data name=\"M.W\" xml:space=\"preserve\">\n    <value>窗口</value>\n  </data>\n  <data name=\"M.ROOT\" xml:space=\"preserve\">\n    <value>主视图</value>\n  </data>\n  <data name=\"M.D.DesktopVisibleAndCloseView\" xml:space=\"preserve\">\n    <value>切换桌面并关闭视图</value>\n  </data>\n  <data name=\"M.D.DesktopVisibleOnly\" xml:space=\"preserve\">\n    <value>仅切换桌面</value>\n  </data>\n  <data name=\"M.D.DesktopShowForSelectedDesktop\" xml:space=\"preserve\">\n    <value>仅显示所选桌面</value>\n  </data>\n  <data name=\"M.ContextMenu\" xml:space=\"preserve\">\n    <value>显示上下文菜单</value>\n  </data>\n  <data name=\"M.W.WindowActiveDesktopVisibleAndCloseView\" xml:space=\"preserve\">\n    <value>激活窗口，切换桌面并关闭视图</value>\n  </data>\n  <data name=\"M.W.WindowActiveDesktopVisibleOnly\" xml:space=\"preserve\">\n    <value>激活窗口，切换桌面</value>\n  </data>\n  <data name=\"M.W.WindowHideFromView\" xml:space=\"preserve\">\n    <value>从视图中隐藏</value>\n  </data>\n  <data name=\"M.W.WindowClose\" xml:space=\"preserve\">\n    <value>关闭窗口</value>\n  </data>\n  <data name=\"M.W.WindowShowForSelectedProcessOnly\" xml:space=\"preserve\">\n    <value>仅显示此程序的窗口</value>\n  </data>\n  <data name=\"M.W.WindowShowForSelectedProcessInSelectedDesktop\" xml:space=\"preserve\">\n    <value>仅显示所选桌面中的活动程序窗口</value>\n  </data>\n  <data name=\"Validation.Mouse.Button.Required\" xml:space=\"preserve\">\n    <value>必须选择鼠标键</value>\n  </data>\n  <data name=\"Mouse.Tips.Exists\" xml:space=\"preserve\">\n    <value>相同的鼠标动作已存在，尝试换一种组合或鼠标键</value>\n  </data>\n  <data name=\"hk_node_toggle_window_filter\" xml:space=\"preserve\">\n    <value>开关窗口过滤器</value>\n  </data>\n</root>"
  },
  {
    "path": "Bridge/VirtualDesktopNotification.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\n\nnamespace VirtualSpace.Commons\n{\n    public enum VirtualDesktopNotificationType\n    {\n        CREATED,\n        DELETED,\n        CURRENT_CHANGED\n    }\n\n    public class VirtualDesktopNotification\n    {\n        public VirtualDesktopNotificationType Type  { get; set; }\n        public Guid                           NewId { get; set; }\n        public Guid                           OldId { get; set; }\n    }\n}"
  },
  {
    "path": "Bridge/Window.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\n\nnamespace VirtualSpace.Config.Events.Entity\n{\n    public class Window\n    {\n        public IntPtr  Handle      { get; set; }\n        public string  Title       { get; set; }\n        public string  WndClass    { get; set; }\n        public string? WinInScreen { get; set; }\n        public int     VdIndex     { get; set; }\n        public int?    ProcessId   { get; set; }\n        public string? ProcessName { get; set; }\n        public string? ProcessPath { get; set; }\n        public string? CommandLine { get; set; }\n\n        public static Window Create(\n            IntPtr handle,\n            string title,\n            string wndClass,\n            int    pId )\n        {\n            return new Window\n            {\n                Handle = handle,\n                Title = title,\n                WndClass = wndClass,\n                ProcessId = pId\n            };\n        }\n    }\n}"
  },
  {
    "path": "COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "Configuration/COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "Configuration/ConfigTemplate.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System.Collections.Generic;\nusing VirtualSpace.Config.DataAnnotations;\nusing VirtualSpace.Config.Entity;\n\nnamespace VirtualSpace.Config\n{\n    public class ConfigTemplate\n    {\n        [PropertyProtector] public Dictionary<string, Profile> Profiles           { get; set; }\n        public                     string                      CurrentProfileName { get; set; }\n        public                     string                      Version            { get; set; }\n        public                     LogConfig                   LogConfig          { get; set; }\n\n        public Dictionary<string, KeyBinding>? KeyBindings { get; set; } = new()\n        {\n            {Const.Hotkey.RISE_VIEW, new KeyBinding {GhkCode = \"_+Ctrl+_+Shift+Tab\", MessageId = Const.Hotkey.Info[Const.Hotkey.RISE_VIEW].MessageId}},\n            {Const.Hotkey.RISE_VIEW_FOR_ACTIVE_APP, new KeyBinding {GhkCode = \"\", MessageId = Const.Hotkey.Info[Const.Hotkey.RISE_VIEW_FOR_ACTIVE_APP].MessageId}},\n            {Const.Hotkey.RISE_VIEW_FOR_CURRENT_VD, new KeyBinding {GhkCode = \"\", MessageId = Const.Hotkey.Info[Const.Hotkey.RISE_VIEW_FOR_CURRENT_VD].MessageId}},\n            {\n                Const.Hotkey.RISE_VIEW_FOR_ACTIVE_APP_IN_CURRENT_VD,\n                new KeyBinding {GhkCode = \"\", MessageId = Const.Hotkey.Info[Const.Hotkey.RISE_VIEW_FOR_ACTIVE_APP_IN_CURRENT_VD].MessageId}\n            },\n            {Const.Hotkey.SHOW_APP_CONTROLLER, new KeyBinding {GhkCode = \"_+Ctrl+Alt+_+F12\", MessageId = Const.Hotkey.Info[Const.Hotkey.SHOW_APP_CONTROLLER].MessageId}},\n            {Const.Hotkey.NAV_LEFT, new KeyBinding {GhkCode = \"\", MessageId = Const.Hotkey.Info[Const.Hotkey.NAV_LEFT].MessageId}},\n            {Const.Hotkey.NAV_RIGHT, new KeyBinding {GhkCode = \"\", MessageId = Const.Hotkey.Info[Const.Hotkey.NAV_RIGHT].MessageId}},\n            {Const.Hotkey.NAV_UP, new KeyBinding {GhkCode = \"\", MessageId = Const.Hotkey.Info[Const.Hotkey.NAV_UP].MessageId}},\n            {Const.Hotkey.NAV_DOWN, new KeyBinding {GhkCode = \"\", MessageId = Const.Hotkey.Info[Const.Hotkey.NAV_DOWN].MessageId}},\n            {Const.Hotkey.SWITCH_BACK_LAST, new KeyBinding {GhkCode = \"\", MessageId = Const.Hotkey.Info[Const.Hotkey.SWITCH_BACK_LAST].MessageId}}\n        };\n\n        public Dictionary<string, MouseAction.Action>? MouseAction  { get; set; } = new();\n        public Dictionary<string, MouseAction.Action>  MouseActions { get; set; } = new();\n\n        [PropertyProtector]\n        public Cluster Cluster { get; set; } = new()\n        {\n            HideMainViewIfItsShown = false,\n            NotificationOnVdChanged = false,\n            ShowVDIndexOnTrayIcon = false,\n            HideOnStart = false\n        };\n\n        public MouseAction.Action GetMouseActionById( string id )\n        {\n            if ( MouseActions.Count == 0 )\n            {\n                MouseActions = Config.MouseAction.Info;\n            }\n\n            return MouseActions.ContainsKey( id )\n                ? MouseActions[id]\n                : Config.MouseAction.Action.DoNothing;\n        }\n    }\n}"
  },
  {
    "path": "Configuration/Configuration.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFrameworks>net6.0-windows</TargetFrameworks>\n        <LangVersion>9</LangVersion>\n        <UseWPF>true</UseWPF>\n        <Nullable>enable</Nullable>\n    </PropertyGroup>\n\n    <ItemGroup>\n        <PackageReference Include=\"Fody\" Version=\"6.6.4\">\n            <PrivateAssets>all</PrivateAssets>\n            <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n        </PackageReference>\n        <PackageReference Include=\"PropertyChanged.Fody\" Version=\"4.1.0\" PrivateAssets=\"All\" />\n    </ItemGroup>\n\n    <ItemGroup>\n        <ProjectReference Include=\"..\\Bridge\\Bridge.csproj\" />\n        <ProjectReference Include=\"..\\Helpers\\Helpers.csproj\" />\n        <ProjectReference Include=\"..\\LinqExpressionBuilder\\LinqExpressionBuilder.csproj\" />\n    </ItemGroup>\n\n    <PropertyGroup>\n        <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>\n    </PropertyGroup>\n\n</Project>"
  },
  {
    "path": "Configuration/Const.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System.Collections.Generic;\nusing System.Windows.Forms;\nusing VirtualSpace.Helpers;\nusing KeyBinding = VirtualSpace.Config.Entity.KeyBinding;\n\nnamespace VirtualSpace.Config\n{\n    public static class Const\n    {\n        public const int    WindowTitleMaxLength   = 2048;\n        public const int    WindowClassMaxLength   = 512;\n        public const int    WindowCheckTimesLimit  = 10;\n        public const int    OneSecond              = 1000;\n        public const int    OneMinute              = 60 * OneSecond;\n        public const int    WindowCloseTimeout     = 60 * OneSecond;\n        public const int    RiseViewInterval       = 500;\n        public const int    SwitchDesktopInterval  = 100;\n        public const int    FakeHideX              = -10000;\n        public const int    FakeHideY              = -10000;\n        public const string ApplicationFrameWindow = \"ApplicationFrameWindow\";\n        public const string WindowsUiCoreWindow    = \"Windows.UI.Core.CoreWindow\";\n        public const string TaskbarCreated         = \"TaskbarCreated\";\n        public const string TaskbarWndClass        = \"Shell_TrayWnd\";\n        public const string WindowsCRLF            = \"\\r\\n\";\n        public const string AppName                = \"VirtualSpace\";\n        public const string HideWindowSplitter     = \"🔙🔜\";\n\n        public static class Window\n        {\n            public const string VD_FRAME_TITLE           = \"VirtualSpace__VirtualDesktopFrame!\";\n            public const string VD_CONTAINER_TITLE       = \"VirtualSpace__VirtualDesktopWindow!\";\n            public const string VD_DRAG_TITLE            = \"VirtualSpace__VirtualDesktopDragWindow!\";\n            public const string VS_CONTROLLER_TITLE      = \"[Virtual Space Controller]\";\n            public const string VS_WINDOW_FILTER_TITLE   = \"VirtualSpace__WindowFilter!\";\n            public const int    WINDOW_FILTER_BAR_HEIGHT = 100;\n        }\n\n        public static class VirtualDesktop\n        {\n            public const int NavHTypeNextRow = 0;\n            public const int NavHTypeSameRow = 1;\n            public const int VdwSizeFloor    = 100;\n        }\n\n        public static class Settings\n        {\n            public const string RuleFileExt     = \".rules\";\n            public const string ClusterFileExt  = \".cluster\";\n            public const string ProfilesFolder  = \"Profiles\";\n            public const string CacheFolder     = \"Cache\";\n            public const string PluginsFolder   = \"Plugins\";\n            public const string LogsFolder      = \"Logs\";\n            public const string SettingsFile    = \"settings.json\";\n            public const string DefaultVersion  = \"2.0\";\n            public const string DefaultLogLevel = \"EVENT\";\n        }\n\n        public static class Reg\n        {\n            public const string RegKeyApp        = @\"Software\\newlooper.com\\VirtualSpace\";\n            public const string RegKeyConfigRoot = \"ConfigRoot\";\n        }\n\n        public static class Args\n        {\n            public const string HIDE_ON_START = \"--HideOnStart\";\n        }\n\n        public static class Hotkey\n        {\n            public const string SPLITTER = \"+\";\n\n            public const string NONE  = \"_\";\n            public const string WIN   = \"Win\";\n            public const string CTRL  = \"Ctrl\";\n            public const string ALT   = \"Alt\";\n            public const string SHIFT = \"Shift\";\n\n            public const  string SVD_TREE_NODE_PREFIX = \"hk_node_svd_\";\n            private const string SVD_FUNC_DESC_PREFIX = \"Switch To Desktop \";\n            public const  string MW_TREE_NODE_PREFIX  = \"hk_node_mw_\";\n            private const string MW_FUNC_DESC_PREFIX  = \"Move To Desktop \";\n            public const  string MWF_TREE_NODE_PREFIX = \"hk_node_mwf_\";\n            private const string MWF_FUNC_DESC_PREFIX = \"Move and Follow To Desktop \";\n\n            ///////////////////////////////////////////////////\n            // 值与控件名称一一对应，若控件名被修改，则此处也须对应改变\n            public const string RISE_VIEW                              = \"hk_node_rise_mainview\";\n            public const string RISE_VIEW_FOR_ACTIVE_APP               = \"hk_node_rise_mainview_for_active_app\";\n            public const string RISE_VIEW_FOR_CURRENT_VD               = \"hk_node_rise_mainview_for_current_vd\";\n            public const string RISE_VIEW_FOR_ACTIVE_APP_IN_CURRENT_VD = \"hk_node_rise_mainview_for_active_app_in_current_vd\";\n            public const string SHOW_APP_CONTROLLER                    = \"hk_node_open_app_controller\";\n            public const string NAV_LEFT                               = \"hk_node_nav_left\";\n            public const string NAV_RIGHT                              = \"hk_node_nav_right\";\n            public const string NAV_UP                                 = \"hk_node_nav_up\";\n            public const string NAV_DOWN                               = \"hk_node_nav_down\";\n            public const string SWITCH_BACK_LAST                       = \"hk_node_svd_back_last\";\n            public const string TOGGLE_WINDOW_FILTER                   = \"hk_node_toggle_window_filter\";\n\n            ////////////////////////////////////////////////////////////////\n            // 可由热键调用的程序功能表\n            // tuple.Item1 => friendly name\n            // tuple.Item2 => UserMessageId\n            // tuple.Item3 => alternate hotkey, 由程序保留，只能在源码中修改\n            public static readonly Dictionary<string, (string FuncDesc, int MessageId, string AltHotKey)> Info = new()\n            {\n                {RISE_VIEW, ( \"Rise MainView\", UserMessage.RiseView, \"LWin+Tab\" )},\n                {RISE_VIEW_FOR_ACTIVE_APP, ( \"Rise MainView For Active App\", UserMessage.RiseViewForActiveApp, \"\" )},\n                {RISE_VIEW_FOR_CURRENT_VD, ( \"Rise MainView For Current Desktop\", UserMessage.RiseViewForCurrentVD, \"\" )},\n                {\n                    RISE_VIEW_FOR_ACTIVE_APP_IN_CURRENT_VD,\n                    ( \"Rise MainView For Active App In Current Virtual Desktop\", UserMessage.RiseViewForActiveAppInCurrentVD, \"\" )\n                },\n                {SHOW_APP_CONTROLLER, ( \"Open AppController\", UserMessage.ShowAppController, \"\" )},\n                {NAV_LEFT, ( \"Left\", UserMessage.NavLeft, \"LWin+Ctrl+Left\" )},\n                {NAV_RIGHT, ( \"Right\", UserMessage.NavRight, \"LWin+Ctrl+Right\" )},\n                {NAV_UP, ( \"Up\", UserMessage.NavUp, \"LWin+Ctrl+Up\" )},\n                {NAV_DOWN, ( \"Down\", UserMessage.NavDown, \"LWin+Ctrl+Down\" )},\n                {SWITCH_BACK_LAST, ( \"Switch Back To Last Desktop\", UserMessage.SwitchBackToLastDesktop, \"\" )},\n                {TOGGLE_WINDOW_FILTER, ( \"Toggle Window Filter\", UserMessage.ToggleWindowFilter, \"\" )}\n            };\n\n            public static string GetFuncDesc( string key )\n            {\n                var func = \"\";\n                if ( Info.ContainsKey( key ) )\n                {\n                    func = Info[key].FuncDesc;\n                }\n                else if ( key.StartsWith( SVD_TREE_NODE_PREFIX ) )\n                {\n                    func = SVD_FUNC_DESC_PREFIX + key.Replace( SVD_TREE_NODE_PREFIX, \"\" );\n                }\n                else if ( key.StartsWith( MW_TREE_NODE_PREFIX ) )\n                {\n                    func = MW_FUNC_DESC_PREFIX + key.Replace( MW_TREE_NODE_PREFIX, \"\" );\n                }\n                else if ( key.StartsWith( MWF_TREE_NODE_PREFIX ) )\n                {\n                    func = MWF_FUNC_DESC_PREFIX + key.Replace( MWF_TREE_NODE_PREFIX, \"\" );\n                }\n\n                return func;\n            }\n\n            public static KeyBinding GetKeyBinding( string key )\n            {\n                var kb = new KeyBinding();\n                if ( Info.ContainsKey( key ) )\n                {\n                    kb.MessageId = Info[key].MessageId;\n                }\n                else if ( key.StartsWith( SVD_TREE_NODE_PREFIX ) )\n                {\n                    kb.MessageId = UserMessage.Meta.SVD_START + int.Parse( key.Replace( SVD_TREE_NODE_PREFIX, \"\" ) );\n                }\n                else if ( key.StartsWith( MW_TREE_NODE_PREFIX ) )\n                {\n                    kb.MessageId = UserMessage.Meta.MW_START + int.Parse( key.Replace( MW_TREE_NODE_PREFIX, \"\" ) );\n                }\n                else if ( key.StartsWith( MWF_TREE_NODE_PREFIX ) )\n                {\n                    kb.MessageId = UserMessage.Meta.MWF_START + int.Parse( key.Replace( MWF_TREE_NODE_PREFIX, \"\" ) );\n                }\n\n                return kb;\n            }\n\n            public static string GetHotkeyExtra( string key )\n            {\n                var extra = \"\";\n                if ( Info.ContainsKey( key ) )\n                {\n                    extra = Info[key].AltHotKey;\n                }\n\n                return extra;\n            }\n        }\n    }\n\n    public static class MouseAction\n    {\n        public enum Action\n        {\n            DoNothing,\n            ContextMenu,\n            DesktopVisibleAndCloseView,\n            DesktopVisibleOnly,\n            WindowActiveDesktopVisibleAndCloseView,\n            WindowActiveDesktopVisibleOnly,\n            WindowClose,\n            WindowHideFromView,\n            WindowShowForSelectedProcessOnly,\n            WindowShowForSelectedProcessInSelectedDesktop,\n            DesktopShowForSelectedDesktop\n        }\n\n        public static          string MOUSE_NODE_DESKTOP_PREFIX = \"mouse_node_d_\";\n        public static          string MOUSE_NODE_WINDOW_PREFIX  = \"mouse_node_w_\";\n        public const           string KEY_SPLITTER              = \"+\";\n        public static readonly string NoneKeyCode               = ( (int)Keys.None ).ToString( \"X2\" );\n\n        private static readonly Dictionary<MouseButtons, string> MouseButtonsName;\n        public static readonly  Dictionary<Keys, string>         KeysName;\n\n        ////////////////////////////////////////////////////////////////\n        // 鼠标动作表，信息包含默认行为\n        public static readonly Dictionary<string, Action> Info1; // ver 1.0\n\n        ////////////////////////////////////////////////////////////////\n        // 鼠标动作表，信息包含默认行为\n        public static readonly Dictionary<string, Action> Info; // ver 2.0\n\n        static MouseAction()\n        {\n            MouseButtonsName = new Dictionary<MouseButtons, string>\n            {\n                {MouseButtons.Left, \"Left\"},\n                {MouseButtons.Middle, \"Middle\"},\n                {MouseButtons.Right, \"Right\"}\n            };\n\n            KeysName = new Dictionary<Keys, string>\n            {\n                {Keys.Control, \"Ctrl\"},\n                {Keys.Alt, \"Alt\"},\n                {Keys.Shift, \"Shift\"}\n            };\n\n            Info = new Dictionary<string, Action>\n            {\n                {MOUSE_NODE_DESKTOP_PREFIX + NoneKeyCode + KEY_SPLITTER + MouseButtonsName[MouseButtons.Left], Action.DesktopVisibleAndCloseView},\n                {MOUSE_NODE_DESKTOP_PREFIX + NoneKeyCode + KEY_SPLITTER + MouseButtonsName[MouseButtons.Middle], Action.DesktopVisibleOnly},\n                {MOUSE_NODE_DESKTOP_PREFIX + NoneKeyCode + KEY_SPLITTER + MouseButtonsName[MouseButtons.Right], Action.ContextMenu},\n\n                {MOUSE_NODE_WINDOW_PREFIX + NoneKeyCode + KEY_SPLITTER + MouseButtonsName[MouseButtons.Left], Action.WindowActiveDesktopVisibleAndCloseView},\n                {MOUSE_NODE_WINDOW_PREFIX + NoneKeyCode + KEY_SPLITTER + MouseButtonsName[MouseButtons.Middle], Action.WindowActiveDesktopVisibleOnly},\n                {MOUSE_NODE_WINDOW_PREFIX + NoneKeyCode + KEY_SPLITTER + MouseButtonsName[MouseButtons.Right], Action.ContextMenu},\n            };\n\n            Info1 = new Dictionary<string, Action>\n            {\n                {MOUSE_NODE_DESKTOP_PREFIX + MouseButtonsName[MouseButtons.Left], Action.DesktopVisibleAndCloseView},\n                {MOUSE_NODE_DESKTOP_PREFIX + MouseButtonsName[MouseButtons.Middle], Action.DesktopVisibleOnly},\n                {MOUSE_NODE_DESKTOP_PREFIX + MouseButtonsName[MouseButtons.Right], Action.ContextMenu},\n                {MOUSE_NODE_DESKTOP_PREFIX + KeysName[Keys.Control] + KEY_SPLITTER + MouseButtonsName[MouseButtons.Left], Action.DoNothing},\n                {MOUSE_NODE_DESKTOP_PREFIX + KeysName[Keys.Control] + KEY_SPLITTER + MouseButtonsName[MouseButtons.Middle], Action.DoNothing},\n                {MOUSE_NODE_DESKTOP_PREFIX + KeysName[Keys.Control] + KEY_SPLITTER + MouseButtonsName[MouseButtons.Right], Action.DoNothing},\n                {MOUSE_NODE_DESKTOP_PREFIX + KeysName[Keys.Alt] + KEY_SPLITTER + MouseButtonsName[MouseButtons.Left], Action.DoNothing},\n                {MOUSE_NODE_DESKTOP_PREFIX + KeysName[Keys.Alt] + KEY_SPLITTER + MouseButtonsName[MouseButtons.Middle], Action.DoNothing},\n                {MOUSE_NODE_DESKTOP_PREFIX + KeysName[Keys.Alt] + KEY_SPLITTER + MouseButtonsName[MouseButtons.Right], Action.DoNothing},\n                {MOUSE_NODE_DESKTOP_PREFIX + KeysName[Keys.Shift] + KEY_SPLITTER + MouseButtonsName[MouseButtons.Left], Action.DoNothing},\n                {MOUSE_NODE_DESKTOP_PREFIX + KeysName[Keys.Shift] + KEY_SPLITTER + MouseButtonsName[MouseButtons.Middle], Action.DoNothing},\n                {MOUSE_NODE_DESKTOP_PREFIX + KeysName[Keys.Shift] + KEY_SPLITTER + MouseButtonsName[MouseButtons.Right], Action.DoNothing},\n\n                {MOUSE_NODE_WINDOW_PREFIX + MouseButtonsName[MouseButtons.Left], Action.WindowActiveDesktopVisibleAndCloseView},\n                {MOUSE_NODE_WINDOW_PREFIX + MouseButtonsName[MouseButtons.Middle], Action.WindowActiveDesktopVisibleOnly},\n                {MOUSE_NODE_WINDOW_PREFIX + MouseButtonsName[MouseButtons.Right], Action.ContextMenu},\n                {MOUSE_NODE_WINDOW_PREFIX + KeysName[Keys.Control] + KEY_SPLITTER + MouseButtonsName[MouseButtons.Left], Action.DoNothing},\n                {MOUSE_NODE_WINDOW_PREFIX + KeysName[Keys.Control] + KEY_SPLITTER + MouseButtonsName[MouseButtons.Middle], Action.DoNothing},\n                {MOUSE_NODE_WINDOW_PREFIX + KeysName[Keys.Control] + KEY_SPLITTER + MouseButtonsName[MouseButtons.Right], Action.DoNothing},\n                {MOUSE_NODE_WINDOW_PREFIX + KeysName[Keys.Alt] + KEY_SPLITTER + MouseButtonsName[MouseButtons.Left], Action.DoNothing},\n                {MOUSE_NODE_WINDOW_PREFIX + KeysName[Keys.Alt] + KEY_SPLITTER + MouseButtonsName[MouseButtons.Middle], Action.DoNothing},\n                {MOUSE_NODE_WINDOW_PREFIX + KeysName[Keys.Alt] + KEY_SPLITTER + MouseButtonsName[MouseButtons.Right], Action.DoNothing},\n                {MOUSE_NODE_WINDOW_PREFIX + KeysName[Keys.Shift] + KEY_SPLITTER + MouseButtonsName[MouseButtons.Left], Action.DoNothing},\n                {MOUSE_NODE_WINDOW_PREFIX + KeysName[Keys.Shift] + KEY_SPLITTER + MouseButtonsName[MouseButtons.Middle], Action.DoNothing},\n                {MOUSE_NODE_WINDOW_PREFIX + KeysName[Keys.Shift] + KEY_SPLITTER + MouseButtonsName[MouseButtons.Right], Action.DoNothing}\n            };\n        }\n\n        public static string GetActionId( MouseButtons mb, Keys key, string prefix )\n        {\n            if ( User32.GetKeyState( (int)Keys.LWin ) < 0 )\n            {\n                key |= Keys.LWin;\n            }\n\n            var keyCode = ( (int)key ).ToString( \"X2\" );\n\n            var actionId = prefix + keyCode + KEY_SPLITTER + MouseButtonsName[mb];\n\n            return actionId;\n        }\n    }\n}"
  },
  {
    "path": "Configuration/Converter/EntityConverter.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace VirtualSpace.Config.Converter\n{\n    public static class EntityConverter\n    {\n        public static void ConvertMouseAction( Dictionary<string, MouseAction.Action> oldFormat, Dictionary<string, MouseAction.Action> newFormat )\n        {\n            var prefix      = string.Empty;\n            var combined    = string.Empty;\n            var modifier    = string.Empty;\n            var mouseButton = string.Empty;\n\n            foreach ( var (maId, ma) in oldFormat )\n            {\n                if ( maId.StartsWith( MouseAction.MOUSE_NODE_DESKTOP_PREFIX ) )\n                {\n                    prefix = MouseAction.MOUSE_NODE_DESKTOP_PREFIX;\n                    combined = maId[MouseAction.MOUSE_NODE_DESKTOP_PREFIX.Length..];\n                }\n                else if ( maId.StartsWith( MouseAction.MOUSE_NODE_WINDOW_PREFIX ) )\n                {\n                    prefix = MouseAction.MOUSE_NODE_WINDOW_PREFIX;\n                    combined = maId[MouseAction.MOUSE_NODE_WINDOW_PREFIX.Length..];\n                }\n\n                if ( combined.Contains( MouseAction.KEY_SPLITTER ) )\n                {\n                    var arrMK = combined.Split( MouseAction.KEY_SPLITTER );\n                    var key   = MouseAction.KeysName.Single( x => x.Value == arrMK[0] ).Key;\n                    modifier = ( (int)key ).ToString( \"X2\" );\n                    mouseButton = arrMK[1];\n                }\n                else\n                {\n                    modifier = MouseAction.NoneKeyCode;\n                    mouseButton = combined;\n                }\n\n                newFormat.Add( prefix + modifier + MouseAction.KEY_SPLITTER + mouseButton, ma );\n            }\n        }\n    }\n}"
  },
  {
    "path": "Configuration/DataAnnotations/PropertyProtectorAttribute.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Linq;\n\nnamespace VirtualSpace.Config.DataAnnotations\n{\n    public class PropertyProtectorAttribute : Attribute\n    {\n        public object[] Values { get; private set; }\n\n        public PropertyProtectorAttribute()\n        {\n        }\n\n        public PropertyProtectorAttribute( byte defaultV, byte min )\n        {\n            Values = new object[] {defaultV, min};\n        }\n\n        public PropertyProtectorAttribute( int defaultV, int min, int max )\n        {\n            Values = new object[] {defaultV, min, max};\n        }\n\n        public PropertyProtectorAttribute( long defaultV, long min, long max )\n        {\n            Values = new object[] {defaultV, min, max};\n        }\n    }\n\n    public abstract class PropertyProtector\n    {\n        public static void Walk( object obj )\n        {\n            var props = from prop in obj.GetType().GetProperties()\n                let attrs = prop.GetCustomAttributes( typeof( PropertyProtectorAttribute ), false )\n                where attrs.Any()\n                select new {Obj = obj, Property = prop, Attr = (PropertyProtectorAttribute)attrs.First()};\n\n            foreach ( var pair in props )\n            {\n                if ( pair.Attr.Values is null ) // an object that have some properties which modified by [PropertyProtector( xxx )]\n                {\n                    var type = pair.Property.PropertyType;\n                    if ( type.FullName.StartsWith( \"System.Collections.Generic.Dictionary\" ) ) // for collection Type, only Dictionary supported for now\n                    {\n                        var dict   = pair.Property.GetValue( pair.Obj );\n                        var values = ( (dynamic)dict ).Values;\n                        foreach ( var v in values )\n                        {\n                            Walk( v );\n                        }\n                    }\n                    else\n                    {\n                        Walk( pair.Property.GetValue( pair.Obj ) ); // a class instance\n                    }\n                }\n                else\n                {\n                    //////////////////////////////////////////////\n                    // if validation fail, reset to default value\n                    // only support byte, int, long for now\n                    switch ( pair.Attr.Values[0] )\n                    {\n                        case byte:\n                        {\n                            var current = (byte)pair.Property.GetValue( obj );\n                            if ( current < (byte)pair.Attr.Values[1] || current > byte.MaxValue )\n                            {\n                                pair.Property.SetValue( obj, pair.Attr.Values[0], null );\n                            }\n\n                            break;\n                        }\n\n                        case int:\n                        {\n                            var current = (int)pair.Property.GetValue( obj );\n                            if ( current < (int)pair.Attr.Values[1] || current > (int)pair.Attr.Values[2] )\n                            {\n                                pair.Property.SetValue( obj, pair.Attr.Values[0], null );\n                            }\n\n                            break;\n                        }\n\n                        case long:\n                        {\n                            var current = (long)pair.Property.GetValue( obj );\n                            if ( current < (long)pair.Attr.Values[1] || current > (long)pair.Attr.Values[2] )\n                            {\n                                pair.Property.SetValue( obj, pair.Attr.Values[0], null );\n                            }\n\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "Configuration/Entity/Cluster.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing VirtualSpace.Config.DataAnnotations;\n\nnamespace VirtualSpace.Config.Entity\n{\n    public class Cluster\n    {\n        public bool HideMainViewIfItsShown     { get; set; }\n        public bool NotificationOnVdChanged    { get; set; }\n        public bool ShowVDIndexOnTrayIcon      { get; set; }\n        public int  StyleOfVDIndexOnTrayIcon   { get; set; } = 0;\n        public bool HideOnStart                { get; set; }\n        public bool ForceFocusForegroundWindow { get; set; } = true;\n        public bool EnableDoubleBufferedForVDW { get; set; } = true;\n        public bool EnableWindowFilter         { get; set; } = false;\n\n        [PropertyProtector( 50L, 30L, 100L )]  public long VdwWallpaperQuality                      { get; set; }\n        [PropertyProtector( 200, 100, 1000 )]  public int  ToggleWindowFilterDoublePressMaxInterval { get; set; }\n        [PropertyProtector( 1000, 100, 1000 )] public int  WindowFilterKeywordScanningInterval      { get; set; }\n    }\n}"
  },
  {
    "path": "Configuration/Entity/Colour.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing VirtualSpace.Config.DataAnnotations;\n\nnamespace VirtualSpace.Config.Entity\n{\n    public class Colour\n    {\n        [PropertyProtector( 55, 1 )] public byte R { get; set; }\n        [PropertyProtector( 55, 1 )] public byte G { get; set; }\n        [PropertyProtector( 55, 1 )] public byte B { get; set; }\n\n        public uint GetLongOfColor()\n        {\n            return (uint)( R * 0x10000 + G * 0x100 + B );\n        }\n    }\n}"
  },
  {
    "path": "Configuration/Entity/KeyBinding.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nnamespace VirtualSpace.Config.Entity\n{\n    public class KeyBinding\n    {\n        public string GhkCode   { get; set; } = \"\";\n        public int    MessageId { get; set; }\n    }\n}"
  },
  {
    "path": "Configuration/Entity/LogConfig.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nnamespace VirtualSpace.Config.Entity\n{\n    public class LogConfig\n    {\n        public bool   ShowLogsInGui { get; set; } = false;\n        public string LogLevel      { get; set; }\n    }\n}"
  },
  {
    "path": "Configuration/Entity/Margin.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing VirtualSpace.Config.DataAnnotations;\n\nnamespace VirtualSpace.Config.Entity\n{\n    public class Margin\n    {\n        public Margin()\n        {\n        }\n\n        public Margin( int all )\n        {\n            Top = all;\n            Right = all;\n            Bottom = all;\n            Left = all;\n        }\n\n        [PropertyProtector( 10, 0, 50 )] public int Top    { get; set; }\n        [PropertyProtector( 10, 0, 50 )] public int Right  { get; set; }\n        [PropertyProtector( 10, 0, 50 )] public int Bottom { get; set; }\n        [PropertyProtector( 10, 0, 50 )] public int Left   { get; set; }\n    }\n}"
  },
  {
    "path": "Configuration/Entity/Mouse.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing VirtualSpace.Config.DataAnnotations;\n\nnamespace VirtualSpace.Config.Entity\n{\n    public class Mouse\n    {\n        public                                       int  LeftClickOnCanvas                  { get; set; }\n        public                                       int  RightClickOnCanvas                 { get; set; }\n        public                                       int  MiddleClickOnCanvas                { get; set; }\n        public                                       bool UseWheelSwitchDesktopWhenOnTaskbar { get; set; }\n        [PropertyProtector( 10, 1, 100 )]     public int  DragSizeFactor                     { get; set; }\n        [PropertyProtector( 100, 100, 1000 )] public int  TaskbarVisibilityThreshold         { get; set; }\n    }\n}"
  },
  {
    "path": "Configuration/Entity/Navigation.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nnamespace VirtualSpace.Config.Entity\n{\n    public class Navigation\n    {\n        public bool CirculationH     { get; set; }\n        public int  CirculationHType { get; set; }\n        public bool CirculationV     { get; set; }\n    }\n}"
  },
  {
    "path": "Configuration/Entity/UserInterface.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing VirtualSpace.Config.DataAnnotations;\n\nnamespace VirtualSpace.Config.Entity\n{\n    public class UserInterface\n    {\n        [PropertyProtector] public             Colour? CanvasBackColor        { get; set; }\n        [PropertyProtector] public             Colour? VDWDefaultBackColor    { get; set; }\n        [PropertyProtector] public             Colour? VDWCurrentBackColor    { get; set; }\n        [PropertyProtector] public             Colour? VDWHighlightBackColor  { get; set; }\n        public                                 float   VDWDragTargetOpacity   { get; set; }\n        public                                 string  Language               { get; set; }\n        public                                 bool    ShowVdName             { get; set; } = true;\n        public                                 bool    ShowVdIndex            { get; set; } = true;\n        [PropertyProtector( 0, 0, 1 )]  public int     ShowVdIndexType        { get; set; }\n        [PropertyProtector( 0, 0, 50 )] public int     VDWPadding             { get; set; }\n        [PropertyProtector( 5, 0, 50 )] public int     VDWBorderSize          { get; set; }\n        [PropertyProtector( 8, 8, 50 )] public int     VDWMargin              { get; set; }\n        [PropertyProtector( 1, 1 )]     public byte    CanvasOpacity          { get; set; }\n        [PropertyProtector]             public Margin? ThumbMargin            { get; set; }\n        public                                 byte    ThumbDragSourceOpacity { get; set; }\n        [PropertyProtector( 0, 0, 7 )] public  int?    DesktopArrangement     { get; set; }\n        public                                 int     Theme                  { get; set; }\n    }\n}"
  },
  {
    "path": "Configuration/Events/Entity/ExpressionTemplate.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Collections.Generic;\n\nnamespace VirtualSpace.Config.Events.Entity\n{\n    public class ExpressionTemplate\n    {\n        public Guid                      id        { get; set; } = Guid.NewGuid();\n        public string?                   condition { get; set; }\n        public List<ExpressionTemplate>? rules     { get; set; }\n        public string?                   type      { get; set; }\n        public string?                   field     { get; set; }\n        public string?                   @operator { get; set; }\n        public Value?                    value     { get; set; }\n    }\n\n    public class Value\n    {\n        public string?       V { get; set; }\n        public List<string>? L { get; set; }\n    }\n}"
  },
  {
    "path": "Configuration/Events/Entity/RuleTemplate.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Text.Json;\nusing PropertyChanged;\n\nnamespace VirtualSpace.Config.Events.Entity\n{\n    [AddINotifyPropertyChangedInterface]\n    public partial class RuleTemplate\n    {\n        [DoNotNotify] public Guid                Id               { get; set; } = Guid.NewGuid();\n        [DoNotNotify] public string?             Name             { get; set; }\n        [DoNotNotify] public string?             Tag              { get; set; }\n        [DoNotNotify] public int                 Weight           { get; set; } = 50;\n        public               bool                Enabled          { get; set; }\n        public               bool                ContinueAfterHit { get; set; }\n        [DoNotNotify] public Func<Window, bool>? Exp;\n        [DoNotNotify] public JsonDocument?       Expression { get; set; }\n        [DoNotNotify] public Behavior?           Action     { get; set; }\n        public               DateTime?           Created    { get; set; }\n        public               DateTime?           Updated    { get; set; }\n    }\n\n    public static class RuleFields\n    {\n        public const string Title       = nameof( Title );\n        public const string ProcessName = nameof( ProcessName );\n        public const string ProcessPath = nameof( ProcessPath );\n        public const string CommandLine = nameof( CommandLine );\n        public const string WndClass    = nameof( WndClass );\n        public const string WinInScreen = nameof( WinInScreen );\n    }\n}"
  },
  {
    "path": "Configuration/Events/Expression/Conditions.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Collections.Concurrent;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text.Encodings.Web;\nusing System.Text.Json;\nusing System.Text.Json.Serialization;\nusing System.Threading;\nusing System.Threading.Channels;\nusing System.Threading.Tasks;\nusing System.Windows.Forms;\nusing LinqExpressionBuilder;\nusing VirtualSpace.AppLogs;\nusing VirtualSpace.Commons;\nusing VirtualSpace.Config.Events.Entity;\nusing VirtualSpace.Helpers;\nusing Process = System.Diagnostics.Process;\n\nnamespace VirtualSpace.Config.Events.Expression\n{\n    public static partial class Conditions\n    {\n        private static readonly JsonParser                        Jp = new();\n        private static          List<RuleTemplate>                _rules;\n        private static readonly Channel<Behavior>                 ActionProducer            = Channels.ActionChannel;\n        private static readonly Channel<Window>                   VisibleWindowsConsumer    = Channels.VisibleWindowsChannel;\n        private static readonly ConcurrentDictionary<IntPtr, int> WindowCheckTimes          = new();\n        public static readonly  ConcurrentBag<IntPtr>             WndHandleIgnoreListByRule = new();\n        private static          long                              _updateRuleLock;\n\n        static Conditions()\n        {\n            _rules = InitRules();\n            BuildRuleExp( _rules );\n            RuleChecker();\n        }\n\n        private static async void RuleChecker()\n        {\n            while ( await VisibleWindowsConsumer.Reader.WaitToReadAsync() )\n            {\n                if ( VisibleWindowsConsumer.Reader.TryRead( out var win ) )\n                {\n                    CheckRulesForWindow( win );\n                }\n            }\n        }\n\n        private static List<RuleTemplate> InitRules()\n        {\n            var path  = Manager.GetRuleFilePath();\n            var rules = new List<RuleTemplate>();\n            if ( !File.Exists( path ) ) return rules;\n\n            rules = ReadRuleFromFile( path );\n\n            return rules;\n        }\n\n        private static void BuildRuleExp( List<RuleTemplate> rules )\n        {\n            foreach ( var rule in rules )\n            {\n                rule.Exp = Jp.ExpressionFromJsonDoc<Window>( rule.Expression );\n            }\n\n            _rules.Sort( ( x, y ) => -x.Weight.CompareTo( y.Weight ) );\n        }\n\n        public static List<RuleTemplate> FetchRules()\n        {\n            return _rules;\n        }\n\n        private static async void CheckRulesForWindow( Window win )\n        {\n            if ( _rules.Count == 0 || Interlocked.Read( ref _updateRuleLock ) != 0 ) return;\n\n            var rules = new List<RuleTemplate>( _rules );\n\n            WindowCheckTimes.TryAdd( win.Handle, 0 );\n\n            var isOnePeriod = WindowCheckTimes[win.Handle] % Const.WindowCheckTimesLimit == 0;\n\n            if ( isOnePeriod )\n            {\n                Logger.Debug( $\"Checking rules for {win.Title}, current profile: {Manager.Configs.CurrentProfileName}\" );\n            }\n\n            await Task.Run( () =>\n            {\n                _ = User32.GetWindowThreadProcessId( win.Handle, out var pId );\n                using var pInfo = Process.GetProcessById( pId );\n\n                win.ProcessName = pInfo.ProcessName;\n                try\n                {\n                    win.ProcessPath = pInfo.MainModule?.FileName;\n                    win.CommandLine = pInfo.GetCommandLineArgs();\n                }\n                catch ( Exception ex )\n                {\n                    Logger.Warning( \"Get Process Info: \" + ex.Message );\n                }\n\n                var screen      = Screen.FromHandle( win.Handle );\n                var screenIndex = 0;\n                var allScreens  = Screen.AllScreens;\n                for ( var i = 0; i < allScreens.Length; i++ )\n                {\n                    if ( screen.DeviceName == allScreens[i].DeviceName )\n                    {\n                        screenIndex = i;\n                        break;\n                    }\n                }\n\n                win.WinInScreen = screenIndex.ToString();\n\n                if ( !User32.IsWindow( win.Handle ) ) return;\n\n                var hasMatchedRule = false;\n\n                var l = new List<Window>();\n\n                foreach ( var r in rules )\n                {\n                    if ( !r.Enabled ) continue;\n                    l.Add( win );\n                    var match = l.Where( r.Exp ).Any();\n                    l.Clear();\n                    if ( match )\n                    {\n                        hasMatchedRule = true;\n                        Logger.Debug( win.Title + $\" match rule [{r.Name}]\" );\n                        r.Action.Handle      = win.Handle;\n                        r.Action.RuleName    = r.Name;\n                        r.Action.WindowTitle = win.Title;\n                        ActionProducer.Writer.TryWrite( r.Action );\n\n                        ////////////////////////////////////////////////////////////////\n                        // 某个窗口可能与多条规则匹配，继续循环就表示所有相应的动作都会按顺序执行\n                        // 最终的方案：给规则添加一个属性，用于指定是否在匹配到规则后继续检查其他规则\n                        // 默认为 false，即匹配到规则后立即退出循环\n                        if ( !r.ContinueAfterHit )\n                            break;\n                    }\n                }\n\n                if ( hasMatchedRule )\n                {\n                    WndHandleIgnoreListByRule.Add( win.Handle );\n                    return;\n                }\n\n                if ( isOnePeriod )\n                {\n                    Logger.Debug( $\"Window [{win.Title}] has no matched rules.\" );\n                }\n\n                if ( Manager.CurrentProfile.IgnoreWindowOnRuleCheckTimeout )\n                {\n                    if ( WindowCheckTimes[win.Handle] >= Const.WindowCheckTimesLimit )\n                    {\n                        Logger.Debug( $\"Try find rules for [{win.Title}] too many times, ignore the window.\" );\n                        WndHandleIgnoreListByRule.Add( win.Handle );\n                    }\n                }\n\n                WindowCheckTimes[win.Handle]++;\n                \n            } ).ConfigureAwait( false );\n        }\n\n        private static List<RuleTemplate> ReadRuleFromFile( string path )\n        {\n            using var fs     = new FileStream( path, FileMode.Open, FileAccess.Read );\n            var       buffer = new byte[fs.Length];\n            _ = fs.Read( buffer, 0, (int)fs.Length );\n            var utf8Reader = new Utf8JsonReader( buffer );\n\n            var readOptions = GetJsonDeserializerOptions();\n            return JsonSerializer.Deserialize<List<RuleTemplate>>( ref utf8Reader, readOptions );\n        }\n\n        public static ExpressionTemplate ParseExpressionTemplate( JsonDocument doc )\n        {\n            var readOptions = GetJsonDeserializerOptions();\n            return JsonSerializer.Deserialize<ExpressionTemplate>( doc, readOptions );\n        }\n\n        private static JsonSerializerOptions? _readOptions;\n        private static JsonSerializerOptions? _writeOptions;\n\n        private static JsonSerializerOptions GetJsonDeserializerOptions()\n        {\n            return _readOptions ??= new JsonSerializerOptions();\n        }\n\n        public static JsonSerializerOptions GetJsonSerializerOptions()\n        {\n            return _writeOptions ??= new JsonSerializerOptions\n            {\n                DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,\n                WriteIndented          = true,\n                Encoder                = JavaScriptEncoder.UnsafeRelaxedJsonEscaping\n            };\n        }\n\n        public static async void SaveRules( List<RuleTemplate> ruleList, string? path = null )\n        {\n            Interlocked.Increment( ref _updateRuleLock );\n\n            _rules = ruleList;\n            BuildRuleExp( _rules );\n\n            Interlocked.Decrement( ref _updateRuleLock );\n\n            path ??= Manager.GetRuleFilePath();\n\n            await File.WriteAllBytesAsync( path, JsonSerializer.SerializeToUtf8Bytes(\n                ruleList, GetJsonSerializerOptions() ) );\n\n            Logger.Info( $\"[RULE]Rules.{Manager.Configs.CurrentProfileName} Saved.\" );\n        }\n\n        public static void SwitchRuleProfile()\n        {\n            Interlocked.Increment( ref _updateRuleLock );\n\n            _rules = InitRules();\n            BuildRuleExp( _rules );\n\n            Interlocked.Decrement( ref _updateRuleLock );\n\n            Logger.Info( $\"[RULE]Switch Rule Profile: {Manager.Configs.CurrentProfileName}\" );\n        }\n    }\n}"
  },
  {
    "path": "Configuration/Events/Expression/Conditions.test.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#if TEST_TEST_TEST\n\nusing System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing LinqExpressionBuilder;\nusing VirtualSpace.Config.Events.Entity;\n\nnamespace VirtualSpace.Config.Events.Expression\n{\n    public static partial class Conditions\n    {\n        private static void TestData( string path )\n        {\n            var test1 = new ExpressionTemplate\n            {\n                field = RuleFields.Title,\n                @operator = Keywords.EndsWith[0],\n                type = Keywords.String,\n                value = new Value {V = \"Notepad3\"}\n            };\n            var test2 = new ExpressionTemplate\n            {\n                condition = Keywords.Or,\n                rules = new List<ExpressionTemplate>\n                {\n                    new()\n                    {\n                        field = RuleFields.Title,\n                        @operator = Keywords.EndsWith[0],\n                        type = Keywords.String,\n                        value = new Value {V = \"Notepad3\"}\n                    },\n                    new()\n                    {\n                        field = RuleFields.Title,\n                        @operator = Keywords.Contains[0],\n                        type = Keywords.String,\n                        value = new Value {V = \"炉石传说\"}\n                    }\n                }\n            };\n\n            var writeOptions = GetJsonSerializerOptions();\n\n            var tempE1 = new RuleTemplate\n            {\n                Name = \"test1\",\n                Expression = JsonDocument.Parse( JsonSerializer.Serialize( test1, writeOptions ) ),\n                Action = new Behavior {MoveToDesktop = 1},\n                Enabled = true,\n                Created = new DateTime( 2021, 10, 11 )\n            };\n            var tempE2 = new RuleTemplate\n            {\n                Name = \"test2\",\n                Expression = JsonDocument.Parse( JsonSerializer.Serialize( test2, writeOptions ) ),\n                Action = new Behavior {MoveToDesktop = 2},\n                Enabled = true,\n                Created = DateTime.Now\n            };\n\n            SaveRules( path, new List<RuleTemplate> {tempE1, tempE2} );\n        }\n    }\n}\n\n#endif"
  },
  {
    "path": "Configuration/FodyWeavers.xml",
    "content": "﻿<Weavers xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"FodyWeavers.xsd\">\n    <PropertyChanged/>\n</Weavers>"
  },
  {
    "path": "Configuration/Manager.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Runtime.CompilerServices;\nusing System.Text.Json;\nusing System.Threading.Tasks;\nusing System.Windows;\nusing Microsoft.Win32;\nusing VirtualSpace.AppLogs;\nusing VirtualSpace.Config.Converter;\nusing VirtualSpace.Config.DataAnnotations;\nusing VirtualSpace.Config.Entity;\nusing VirtualSpace.Config.Events.Expression;\nusing VirtualSpace.Config.Profiles;\nusing Settings = VirtualSpace.Config.Const.Settings;\n\nnamespace VirtualSpace.Config\n{\n    public static class Manager\n    {\n        public static ConfigTemplate Configs;\n        public static string         AppPath;\n        public static string         AppRootFolder;\n        public static string         ProfileFolder;\n        public static string         CacheFolder;\n        public static string         PluginsFolder;\n        public static string         ConfigRootFolder;\n        public static string         ConfigFilePath;\n\n        public static Profile CurrentProfile => Configs.Profiles[Configs.CurrentProfileName];\n\n        public static bool Init()\n        {\n            try\n            {\n                AppPath = Environment.ProcessPath!;\n                AppRootFolder = Directory.GetParent( AppPath )!.FullName;\n\n                ConfigRootFolder = GetConfigRoot();\n                ConfigFilePath = Path.Combine( ConfigRootFolder, Settings.SettingsFile );\n\n                CheckFolders();\n\n                InitConfig( ConfigFilePath );\n\n                LogManager.SetLogLevel( Configs.LogConfig.LogLevel );\n            }\n            catch ( Exception ex )\n            {\n                MessageBox.Show( \"File Access Error.\\n\" + ex.Message, @\"Error\", MessageBoxButton.OK, MessageBoxImage.Error );\n                return false;\n            }\n\n            return true;\n        }\n\n        private static void InitConfig( string filePath )\n        {\n            if ( File.Exists( filePath ) )\n            {\n                using var fs     = new FileStream( filePath, FileMode.Open, FileAccess.Read );\n                var       buffer = new byte[fs.Length];\n                _ = fs.Read( buffer, 0, (int)fs.Length );\n                var utf8Reader = new Utf8JsonReader( buffer );\n                Configs = JsonSerializer.Deserialize<ConfigTemplate>( ref utf8Reader );\n                var cluster = ReadCluster();\n                if ( cluster is not null )\n                {\n                    Configs.Cluster = cluster;\n                }\n\n                PropertyProtector.Walk( Configs );\n\n                if ( Configs.MouseActions.Count == 0 )\n                {\n                    Logger.Info( \"Missing MouseActions, Try find old version from configs.\" );\n                    if ( Configs.MouseAction is null || Configs.MouseAction.Count == 0 )\n                    {\n                        Logger.Info( \"Old version MouseActions not found, Using native default.\" );\n                        Configs.MouseActions = MouseAction.Info;\n                    }\n                    else\n                    {\n                        Logger.Info( \"Old version MouseActions found, try to convert to new version.\" );\n                        try\n                        {\n                            EntityConverter.ConvertMouseAction( Configs.MouseAction, Configs.MouseActions );\n                        }\n                        catch\n                        {\n                            Logger.Info( \"Convert MouseAction failed, Using native default.\" );\n                            Configs.MouseActions = MouseAction.Info;\n                        }\n                    }\n                }\n\n                Logger.Info( $\"Settings File Loaded, Version: {Configs.Version}, Current Profile: {Configs.CurrentProfileName}\" );\n            }\n            else\n            {\n                Logger.Info( \"Settings File Not Found, Create From Default Template.\" );\n                Configs = new ConfigTemplate\n                {\n                    CurrentProfileName = nameof( Default ),\n                    Version = Settings.DefaultVersion,\n                    LogConfig = new LogConfig {LogLevel = Settings.DefaultLogLevel},\n                    Profiles = new Dictionary<string, Profile>\n                    {\n                        {nameof( Default ), new Default()}\n                    },\n                    MouseActions = MouseAction.Info\n                };\n\n                PropertyProtector.Walk( Configs );\n                \n                Save( filePath, \"init\", \"Setting File\" );\n                SaveCluster( Configs.Cluster );\n            }\n        }\n\n        public static async void Save( string? filePath = null, object? reason = null, [CallerArgumentExpression( \"reason\" )] string reasonName = \"\" )\n        {\n            filePath ??= ConfigFilePath;\n            try\n            {\n                var contents = JsonSerializer.SerializeToUtf8Bytes( Configs, JsonWriteOptions );\n                await File.WriteAllBytesAsync( filePath, contents ).ConfigureAwait( false );\n                Logger.Info( $\"Settings Saved [{reasonName}: {reason}].\" );\n\n                if ( reasonName.Contains( \".Configs.Cluster\" ) )\n                    SaveCluster( Configs.Cluster );\n            }\n            catch ( Exception ex )\n            {\n                Logger.Error( \"Failed to save Settings: \" + ex.Message );\n            }\n        }\n\n        public static async void SwitchProfile( string name )\n        {\n            Configs.CurrentProfileName = name;\n            var cluster = ReadCluster(); // after CurrentProfileName changed\n            if ( cluster is not null )\n            {\n                Configs.Cluster = cluster;\n            }\n\n            Conditions.SwitchRuleProfile(); // after CurrentProfileName changed\n\n            try\n            {\n                var contents = JsonSerializer.SerializeToUtf8Bytes( Configs, JsonWriteOptions );\n                await File.WriteAllBytesAsync( ConfigFilePath, contents ).ConfigureAwait( false );\n                Logger.Info( $\"[Profile]Switch: {name}\" );\n            }\n            catch ( Exception ex )\n            {\n                Logger.Error( \"Failed to save Settings: \" + ex.Message );\n            }\n\n            ProfileChanged?.Invoke( null, null );\n        }\n\n        public static event EventHandler<EventArgs>? ProfileChanged;\n\n        public static void SaveCluster( Cluster cluster )\n        {\n            SaveProfile( Path.Combine( ProfileFolder, Configs.CurrentProfileName + Settings.ClusterFileExt ), cluster );\n        }\n\n        private static Cluster? ReadCluster()\n        {\n            return ReadProfile<Cluster>( Path.Combine( ProfileFolder, Configs.CurrentProfileName + Settings.ClusterFileExt ) );\n        }\n\n        private static async void SaveProfile<T>( string path, T p )\n        {\n            try\n            {\n                var content = JsonSerializer.SerializeToUtf8Bytes( p, JsonWriteOptions );\n                await File.WriteAllBytesAsync( path, content );\n\n                Logger.Info( $\"[Profile]{typeof( T ).Name}.{Configs.CurrentProfileName} Saved.\" );\n            }\n            catch ( Exception ex )\n            {\n                Logger.Error( $\"Failed to save profile of {typeof( T ).Name}: {ex.Message}\" );\n            }\n        }\n\n        private static T? ReadProfile<T>( string path )\n        {\n            if ( !File.Exists( path ) )\n                return default;\n            try\n            {\n                using var fs     = new FileStream( path, FileMode.Open, FileAccess.Read );\n                var       buffer = new byte[fs.Length];\n                _ = fs.Read( buffer, 0, (int)fs.Length );\n                var utf8Reader = new Utf8JsonReader( buffer );\n                return JsonSerializer.Deserialize<T>( ref utf8Reader );\n            }\n            catch ( Exception ex )\n            {\n                Logger.Error( $\"Failed to read profile of {typeof( T ).Name}: {ex.Message}\" );\n                return default;\n            }\n        }\n\n        public static async void DeleteFilesOfProfile( string profileName )\n        {\n            var dir = new DirectoryInfo( ProfileFolder );\n            await Task.Run( () =>\n            {\n                try\n                {\n                    foreach ( var file in dir.EnumerateFiles( profileName + \".*\" ) ) // such violent\n                    {\n                        file.Delete();\n                    }\n                }\n                catch ( Exception ex )\n                {\n                    Logger.Error( $\"Failed to delete related files of profile {profileName}: {ex.Message}\" );\n                }\n            } );\n        }\n\n        public static void SetConfigRoot( string path )\n        {\n            using var vsReg = Registry.CurrentUser.CreateSubKey( Const.Reg.RegKeyApp );\n            vsReg.SetValue( Const.Reg.RegKeyConfigRoot, path );\n            ConfigRootFolder = path;\n        }\n\n        private static string GetConfigRoot()\n        {\n            using var vsReg         = Registry.CurrentUser.CreateSubKey( Const.Reg.RegKeyApp );\n            var       configRootReg = vsReg.GetValue( Const.Reg.RegKeyConfigRoot );\n            if ( configRootReg is null || !Directory.Exists( configRootReg.ToString() ) )\n            {\n                return AppRootFolder;\n            }\n\n            return configRootReg.ToString();\n        }\n\n        private static void CheckFolders()\n        {\n            ProfileFolder = Path.Combine( ConfigRootFolder, Settings.ProfilesFolder );\n            Directory.CreateDirectory( ProfileFolder );\n\n            CacheFolder = Path.Combine( AppRootFolder, Settings.CacheFolder );\n            Directory.CreateDirectory( CacheFolder );\n\n            PluginsFolder = Path.Combine( AppRootFolder, Settings.PluginsFolder );\n            Directory.CreateDirectory( PluginsFolder );\n        }\n\n        public static string GetRuleFilePath( string? profile = null )\n        {\n            CheckFolders();\n            return string.IsNullOrEmpty( profile )\n                ? Path.Combine( ProfileFolder, Configs.CurrentProfileName + Settings.RuleFileExt )\n                : Path.Combine( ProfileFolder, profile + Settings.RuleFileExt );\n        }\n\n        public static string GetCachePath()\n        {\n            CheckFolders();\n            return CacheFolder;\n        }\n\n        public static string GetPluginsPath()\n        {\n            CheckFolders();\n            return PluginsFolder;\n        }\n\n        private static readonly JsonSerializerOptions JsonWriteOptions = new() {WriteIndented = true};\n    }\n}"
  },
  {
    "path": "Configuration/Profile.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing VirtualSpace.Config.DataAnnotations;\nusing VirtualSpace.Config.Entity;\n\nnamespace VirtualSpace.Config\n{\n    public class Profile\n    {\n        [PropertyProtector] public               UserInterface UI                             { get; set; }\n        public                                   bool          DaemonAutoStart                { get; set; }\n        [PropertyProtector( 0, 0, 3600 )] public int           DaemonAutoStartDelay           { get; set; }\n        public                                   List<Guid>?   DesktopOrder                   { get; set; }\n        [PropertyProtector] public               Mouse         Mouse                          { get; set; }\n        public                                   bool          IgnoreWindowOnRuleCheckTimeout { get; set; } = true;\n\n        public Navigation Navigation { get; set; } = new()\n        {\n            CirculationH = false,\n            CirculationV = false,\n            CirculationHType = 0\n        };\n\n        public Profile Clone()\n        {\n            var profile = JsonSerializer.Deserialize<Profile>( JsonSerializer.Serialize( this ) );\n            return profile!;\n        }\n    }\n}"
  },
  {
    "path": "Configuration/Profiles/Default.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System.Drawing;\nusing VirtualSpace.Config.Entity;\n\nnamespace VirtualSpace.Config.Profiles\n{\n    public class Default : Profile\n    {\n        public Default()\n        {\n            UI = new UserInterface\n            {\n                CanvasOpacity = 100,\n                CanvasBackColor = new Colour {R = 55, G = 55, B = 55},\n                VDWMargin = 8,\n                VDWBorderSize = 1,\n                VDWPadding = 0,\n                VDWDefaultBackColor = new Colour {R = 55, G = 55, B = 55},\n                VDWCurrentBackColor = new Colour {R = Color.Beige.R, G = Color.Beige.G, B = Color.Beige.B},\n                VDWHighlightBackColor = new Colour {R = Color.Tomato.R, G = Color.Tomato.G, B = Color.Tomato.B},\n                VDWDragTargetOpacity = 0.8f,\n                ThumbMargin = new Margin {Top = 20, Left = 10},\n                ThumbDragSourceOpacity = 150,\n                Language = \"en\",\n                DesktopArrangement = 0,\n                ShowVdName = true,\n                ShowVdIndex = true,\n                ShowVdIndexType = 0\n            };\n            DaemonAutoStart = true;\n            Mouse = new Mouse\n            {\n                DragSizeFactor = 10,\n                LeftClickOnCanvas = 1,\n                RightClickOnCanvas = 0,\n                MiddleClickOnCanvas = 0,\n                UseWheelSwitchDesktopWhenOnTaskbar = false,\n                TaskbarVisibilityThreshold = 100\n            };\n            Navigation = new Navigation\n            {\n                CirculationH = false,\n                CirculationV = false,\n                CirculationHType = 0\n            };\n        }\n    }\n}"
  },
  {
    "path": "Helpers/COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "Helpers/DwmApi.cs",
    "content": "﻿using System;\nusing System.Runtime.InteropServices;\n\nnamespace VirtualSpace.Helpers\n{\n    public static class DwmApi\n    {\n        [Flags]\n        public enum DwmWindowAttribute : uint\n        {\n            /// <summary>\n            ///     Determines whether non-client rendering is enabled. Use this value only with DwmGetWindowAttribute. The retrieved value is of type BOOL. TRUE if non-client\n            ///     rendering is enabled; otherwise, FALSE.\n            /// </summary>\n            DWMWA_NCRENDERING_ENABLED = 1,\n\n            /// <summary>\n            ///     The non-client rendering policy. Use this value only with DwmSetWindowAttribute, with its pvAttribute pointing to a value from the DWMNCRENDERINGPOLICY\n            ///     enumeration.\n            /// </summary>\n            DWMWA_NCRENDERING_POLICY,\n\n            /// <summary>\n            ///     Enable or forcibly disable DWM transitions. Use this value only with DwmSetWindowAttribute, with its pvAttribute pointing to a value of TRUE to disable\n            ///     transitions or FALSE to enable transitions.\n            /// </summary>\n            DWMWA_TRANSITIONS_FORCEDISABLED,\n\n            /// <summary>\n            ///     Allow content rendered in the non-client area to be visible on the frame drawn by DWM. Use this value only with DwmSetWindowAttribute, with its pvAttribute\n            ///     pointing to a value of TRUE to allow content rendered in the non-client area to be visible on the frame; otherwise, FALSE.\n            /// </summary>\n            DWMWA_ALLOW_NCPAINT,\n\n            /// <summary>\n            ///     Retrieves the bounds of the caption button area in the window-relative space. Use this value only with DwmGetWindowAttribute. The retrieved value is of\n            ///     type RECT.\n            /// </summary>\n            DWMWA_CAPTION_BUTTON_BOUNDS,\n\n            /// <summary>\n            ///     Specifies whether non-client content is right-to-left (RTL) mirrored. Use this value only with DwmSetWindowAttribute, with its pvAttribute pointing to a\n            ///     value of TRUE if the non-client content is right-to-left (RTL) mirrored; otherwise, FALSE.\n            /// </summary>\n            DWMWA_NONCLIENT_RTL_LAYOUT,\n\n            /// <summary>\n            ///     Force the window to display an iconic thumbnail or peek representation (a static bitmap), even if a live or snapshot representation of the window is\n            ///     available. This value normally is set during a window's creation and not changed throughout the window's lifetime. Some scenarios, however, might require\n            ///     the value to change over time. Use this value only with DwmSetWindowAttribute, with its pvAttribute pointing to a value of TRUE to require a iconic\n            ///     thumbnail or peek representation; otherwise, FALSE.\n            /// </summary>\n            DWMWA_FORCE_ICONIC_REPRESENTATION,\n\n            /// <summary>\n            ///     Sets how Flip3D treats the window. Use this value only with DwmSetWindowAttribute, with its pvAttribute pointing to a value from the DWMFLIP3DWINDOWPOLICY\n            ///     enumeration.\n            /// </summary>\n            DWMWA_FLIP3D_POLICY,\n\n            /// <summary>\n            ///     Retrieves the extended frame bounds rectangle in screen space. Use this value only with DwmGetWindowAttribute. The retrieved value is of type RECT.\n            /// </summary>\n            DWMWA_EXTENDED_FRAME_BOUNDS,\n\n            /// <summary>\n            ///     The window can provide a bitmap for use by DWM as an iconic thumbnail or peek representation (a static bitmap) for the window. This value can be specified\n            ///     with DWMWA_FORCE_ICONIC_REPRESENTATION. This value normally is set during a window's creation and not changed throughout the window's lifetime. Some\n            ///     scenarios, however, might require the value to change over time. Use this value only with DwmSetWindowAttribute, with its pvAttribute pointing to a value\n            ///     of TRUE to inform DWM that the window will provide an iconic thumbnail or peek representation; otherwise, FALSE.\n            /// </summary>\n            DWMWA_HAS_ICONIC_BITMAP,\n\n            /// <summary>\n            ///     Do not show peek preview for the window. The peek view shows a full-sized preview of the window when the mouse hovers over the window's thumbnail in the\n            ///     taskbar. If this attribute is set, hovering the mouse pointer over the window's thumbnail dismisses peek (in case another window in the group has a peek\n            ///     preview showing). Use this value only with DwmSetWindowAttribute, with its pvAttribute pointing to a value of TRUE to prevent peek functionality; FALSE to\n            ///     allow it.\n            /// </summary>\n            DWMWA_DISALLOW_PEEK,\n\n            /// <summary>\n            ///     Prevents a window from fading to a glass sheet when peek is invoked. Use this value only with DwmSetWindowAttribute, with its pvAttribute pointing to a\n            ///     value of TRUE to prevent the window from fading during another window's peek; FALSE for normal behavior.\n            /// </summary>\n            DWMWA_EXCLUDED_FROM_PEEK,\n\n            /// <summary>\n            ///     Do not use.\n            /// </summary>\n            DWMWA_CLOAK,\n\n            /// <summary>\n            ///     Use with DwmGetWindowAttribute.\n            /// </summary>\n            DWMWA_CLOAKED,\n\n            /// <summary>\n            ///     Use with DwmSetWindowAttribute. Freeze the window's thumbnail image with its current visuals. Do no further live updates on the thumbnail image to match\n            ///     the window's contents.\n            /// </summary>\n            DWMWA_FREEZE_REPRESENTATION,\n\n            /// <summary>\n            ///     The maximum recognized DWMWA value, used for validation purposes.\n            /// </summary>\n            DWMWA_LAST\n        }\n\n        public static readonly int DWM_TNP_VISIBLE         = 0x8;\n        public static readonly int DWM_TNP_OPACITY         = 0x4;\n        public static readonly int DWM_TNP_RECTDESTINATION = 0x1;\n\n        [DllImport( \"dwmapi.dll\" )]\n        public static extern int DwmRegisterThumbnail( IntPtr dest, IntPtr src, out IntPtr thumb );\n\n        [DllImport( \"dwmapi.dll\" )]\n        public static extern int DwmUnregisterThumbnail( IntPtr thumb );\n\n        [DllImport( \"dwmapi.dll\" )]\n        public static extern int DwmQueryThumbnailSourceSize( IntPtr thumb, out SIZE size );\n\n        [DllImport( \"dwmapi.dll\" )]\n        public static extern int DwmUpdateThumbnailProperties( IntPtr hThumb, ref DWM_THUMBNAIL_PROPERTIES props );\n\n        [DllImport( \"dwmapi.dll\" )]\n        public static extern int DwmGetWindowAttribute( IntPtr hWnd, uint dwAttribute, out int pvAttribute, int cbAttribute );\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct DWM_THUMBNAIL_PROPERTIES\n    {\n        public int  dwFlags;\n        public RECT rcDestination;\n        public RECT rcSource;\n        public byte opacity;\n        public bool fVisible;\n        public bool fSourceClientAreaOnly;\n    }\n}"
  },
  {
    "path": "Helpers/GlobalHotKey.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\n\nnamespace VirtualSpace.Helpers\n{\n    public static class GlobalHotKey\n    {\n        [Flags]\n        public enum KeyModifiers\n        {\n            None       = 0,\n            Alt        = 1,\n            Ctrl       = 2,\n            Shift      = 4,\n            WindowsKey = 8\n        }\n\n        private static          IntPtr    _handle = IntPtr.Zero;\n        private static readonly List<int> Ids     = new();\n\n        public static bool RegHotKey( IntPtr hWnd, int id, KeyModifiers fsModifiers, int vk )\n        {\n            _handle = hWnd;\n            Ids.Add( id );\n            return RegisterHotKey( hWnd, id, fsModifiers, vk );\n        }\n\n        [DllImport( \"user32.dll\", SetLastError = true )]\n        private static extern bool RegisterHotKey( IntPtr hWnd, int id, KeyModifiers fsModifiers, int vk );\n\n        [DllImport( \"user32.dll\", SetLastError = true )]\n        public static extern bool UnregisterHotKey( IntPtr hWnd, int id );\n\n        public static void UnRegAllHotKey()\n        {\n            foreach ( var id in Ids )\n            {\n                UnregisterHotKey( _handle, id );\n            }\n        }\n    }\n}"
  },
  {
    "path": "Helpers/Helpers.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFrameworks>net6.0-windows</TargetFrameworks>\n        <Nullable>enable</Nullable>\n        <UseWindowsForms>True</UseWindowsForms>\n        <LangVersion>9</LangVersion>\n    </PropertyGroup>\n\n    <ItemGroup>\n        <PackageReference Include=\"System.Management\" Version=\"6.0.0\" />\n        <PackageReference Include=\"TaskScheduler\" Version=\"2.10.1\" />\n    </ItemGroup>\n\n    <ItemGroup>\n      <ProjectReference Include=\"..\\Logger\\Logger.csproj\" />\n    </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "Helpers/Images.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Drawing;\nusing System.Drawing.Imaging;\nusing System.IO;\nusing System.Security.Cryptography;\nusing System.Text;\nusing System.Text.RegularExpressions;\nusing VirtualSpace.AppLogs;\n\nnamespace VirtualSpace.Helpers\n{\n    internal static class PathInfo\n    {\n        public const string WIDTH_HEIGHT_SPLITTER = \"x\";\n    }\n\n    public static class Images\n    {\n        public static Bitmap GetScaledBitmap( int width, int height, string path, ref Wallpaper wp, string cachePath, long quality )\n        {\n            var cached = Wallpaper.CachedWallPaper( path, cachePath, width, height );\n\n            if ( cached != null ) return cached;\n            using ( var src = new Bitmap( path ) )\n            {\n                var dest = new Bitmap( width, height, PixelFormat.Format32bppPArgb );\n                using ( var gr = Graphics.FromImage( dest ) )\n                {\n                    gr.DrawImage( src, new Rectangle( Point.Empty, dest.Size ) );\n                }\n\n                var md5Path = Wallpaper.Md5Hash( path );\n                var file = Path.Combine( cachePath, md5Path.Str0, md5Path.Str1, width + PathInfo.WIDTH_HEIGHT_SPLITTER + height,\n                    md5Path.FullString + \"_\" + Environment.CurrentManagedThreadId );\n\n                // dest.Save( file, ImageFormat.Jpeg );\n\n                var jpgEncoder        = GetEncoder( ImageFormat.Jpeg );\n                var encoder           = System.Drawing.Imaging.Encoder.Quality;\n                var encoderParameters = new EncoderParameters( 1 );\n                var encoderParameter  = new EncoderParameter( encoder, quality );\n                encoderParameters.Param[0] = encoderParameter;\n                dest.Save( file, jpgEncoder, encoderParameters );\n\n                wp.Fullpath = file;\n\n                return dest;\n            }\n        }\n\n        private static ImageCodecInfo GetEncoder( ImageFormat format )\n        {\n            var codecs = ImageCodecInfo.GetImageEncoders();\n            foreach ( var codec in codecs )\n            {\n                if ( codec.FormatID == format.Guid )\n                {\n                    return codec;\n                }\n            }\n\n            return null;\n        }\n\n        public static Icon BytesToIcon( object bytes )\n        {\n            using var ms = new MemoryStream( (byte[])bytes );\n            return new Icon( ms );\n        }\n\n        public static Bitmap BytesToBitmap( object bytes )\n        {\n            using var ms = new MemoryStream( (byte[])bytes );\n            return new Bitmap( ms );\n        }\n    }\n\n    public class Wallpaper\n    {\n        public Bitmap? Image    { get; set; }\n        public Color   Color    { get; set; }\n        public string? Fullpath { get; set; }\n\n        public static Bitmap? CachedWallPaper( string path, string cachePath, int width, int height )\n        {\n            var cached = CachedWallPaperInfo( path, cachePath, width, height );\n            return cached.Exists ? new Bitmap( cached.Path ) : null;\n        }\n\n        public static (bool Exists, string Path) CachedWallPaperInfo( string path, string cachePath, int width, int height )\n        {\n            var md5Path    = Md5Hash( path );\n            var targetPath = Path.Combine( cachePath, md5Path.Str0, md5Path.Str1, width + PathInfo.WIDTH_HEIGHT_SPLITTER + height );\n            Directory.CreateDirectory( targetPath );\n            var filepath = Path.Combine( targetPath, md5Path.FullString );\n\n            return new ValueTuple<bool, string>( File.Exists( filepath ), filepath );\n        }\n\n        public static (string FullString, string Str0, string Str1) Md5Hash( string input )\n        {\n            var md5        = MD5.Create();\n            var inputBytes = Encoding.ASCII.GetBytes( input );\n            var hashBytes  = md5.ComputeHash( inputBytes );\n\n            var sb = new StringBuilder();\n            foreach ( var b in hashBytes )\n            {\n                sb.Append( b.ToString( \"x2\" ) );\n            }\n\n            var md5Str = sb.ToString();\n\n            return new ValueTuple<string, string, string>(\n                md5Str,\n                md5Str.Substring( 0, 1 ),\n                md5Str.Substring( 1, 1 )\n            );\n        }\n\n        public void Release()\n        {\n            Image?.Dispose();\n            Image = null;\n            if ( string.IsNullOrEmpty( Fullpath ) ) return;\n            try\n            {\n                var file = Regex.Replace( Fullpath, @\"(.*?)_\\d+$\", \"$1\" );\n                if ( !File.Exists( file ) )\n                    File.Move( Fullpath, file );\n            }\n            catch ( Exception ex )\n            {\n                Logger.Warning( \"Delete cache file: \" + ex.Message );\n            }\n            finally\n            {\n                File.Delete( Fullpath );\n            }\n        }\n    }\n}"
  },
  {
    "path": "Helpers/Kernel32.cs",
    "content": "﻿using System;\nusing System.Runtime.InteropServices;\n\nnamespace VirtualSpace.Helpers\n{\n    public static class Kernel32\n    {\n        [DllImport( \"kernel32.dll\", CharSet = CharSet.Unicode, SetLastError = true )]\n        public static extern IntPtr GetModuleHandle( string lpModuleName );\n    }\n}"
  },
  {
    "path": "Helpers/LowLevelHooks.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\nusing System.Windows.Forms;\n\nnamespace VirtualSpace.Helpers\n{\n    public static class LowLevelHooks\n    {\n        public static readonly IntPtr Handled = (IntPtr)1;\n    }\n\n    public static class LowLevelKeyboardHook\n    {\n        public const   int             WM_KEYDOWN     = 0x0100;\n        public const   int             WM_KEYUP       = 0x0101;\n        public const   int             DUMMY_KEY      = 0xFF;\n        private const  int             WH_KEYBOARD_LL = 13;\n        private static User32.HookProc _hookProc;\n\n        public static IntPtr HookId { get; private set; } = IntPtr.Zero;\n\n        public static void SetHook( User32.HookProc proc )\n        {\n            _hookProc = proc;\n            HookId = User32.SetWindowsHookEx( WH_KEYBOARD_LL, _hookProc, Kernel32.GetModuleHandle( null ), 0 );\n        }\n\n        public static void MultipleKeyDown( List<Keys> keys )\n        {\n            SendKeys( keys, 0 );\n        }\n\n        public static void MultipleKeyUp( List<Keys> keys )\n        {\n            SendKeys( keys, KEYEVENTF.KEYUP );\n        }\n\n        public static void MultipleKeyPress( List<Keys> keys )\n        {\n            SendKeysCombine( keys );\n        }\n\n        private static void SendKeys( List<Keys> keys, KEYEVENTF flags )\n        {\n            var inputs = new INPUT[keys.Count];\n            for ( var pos = 0; pos < keys.Count; pos++ )\n            {\n                inputs[pos].Type = InputType.INPUT_KEYBOARD;\n                inputs[pos].Data.Keyboard = new KEYBDINPUT\n                {\n                    Vk = (ushort)keys[pos],\n                    Scan = 0,\n                    Flags = flags,\n                    Time = 0,\n                    ExtraInfo = IntPtr.Zero\n                };\n            }\n\n            var result = User32.SendInput( Convert.ToUInt32( inputs.Length ), inputs, Marshal.SizeOf( typeof( INPUT ) ) );\n            if ( result == 0 )\n                throw new Exception();\n        }\n\n        private static void SendKeysCombine( List<Keys> keys )\n        {\n            var inputs = new INPUT[keys.Count * 2];\n            for ( var i = 0; i < keys.Count; i++ )\n            {\n                inputs[i].Type = InputType.INPUT_KEYBOARD;\n                inputs[i].Data.Keyboard = new KEYBDINPUT\n                {\n                    Vk = (ushort)keys[i],\n                    Scan = 0,\n                    Flags = 0,\n                    Time = 0,\n                    ExtraInfo = IntPtr.Zero\n                };\n                inputs[inputs.Length - i - 1].Type = InputType.INPUT_KEYBOARD;\n                inputs[inputs.Length - i - 1].Data.Keyboard = new KEYBDINPUT\n                {\n                    Vk = (ushort)keys[i],\n                    Scan = 0,\n                    Flags = KEYEVENTF.KEYUP,\n                    Time = 0,\n                    ExtraInfo = IntPtr.Zero\n                };\n            }\n\n            var result = User32.SendInput( Convert.ToUInt32( inputs.Length ), inputs, Marshal.SizeOf( typeof( INPUT ) ) );\n            if ( result == 0 )\n                throw new Exception();\n        }\n\n        public static bool IsKeyHold( Keys key )\n        {\n            return User32.GetAsyncKeyState( (int)key ) < 0;\n        }\n\n        public static void UnHook()\n        {\n            User32.UnhookWindowsHookEx( HookId );\n        }\n\n        public struct KBDLLHOOKSTRUCT\n        {\n            public  int                  vkCode;\n            private int                  scanCode;\n            public  KBDLLHOOKSTRUCTFlags flags;\n            private int                  time;\n            private int                  dwExtraInfo;\n        }\n\n        [Flags]\n        public enum KBDLLHOOKSTRUCTFlags : uint\n        {\n            LLKHF_EXTENDED = 0x01,\n            LLKHF_INJECTED = 0x10,\n            LLKHF_ALTDOWN  = 0x20,\n            LLKHF_UP       = 0x80,\n        }\n    }\n\n    public static class LowLevelMouseHook\n    {\n        private const  int             WH_MOUSE_LL   = 14;\n        public const   int             WM_MOUSEWHEEL = 0x020A;\n        private static User32.HookProc _hookProc;\n\n        public static IntPtr HookId { get; private set; } = IntPtr.Zero;\n\n        public static void SetHook( User32.HookProc proc )\n        {\n            _hookProc = proc;\n            HookId = User32.SetWindowsHookEx( WH_MOUSE_LL, _hookProc, Kernel32.GetModuleHandle( null ), 0 );\n        }\n\n        public static void UnHook()\n        {\n            User32.UnhookWindowsHookEx( HookId );\n        }\n\n        [StructLayout( LayoutKind.Sequential )]\n        public struct MSLLHOOKSTRUCT\n        {\n            public POINT   pt;\n            public int     mouseData; // be careful, this must be ints, not uints.\n            public int     flags;\n            public int     time;\n            public UIntPtr dwExtraInfo;\n        }\n    }\n}"
  },
  {
    "path": "Helpers/StringHelper.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Text.RegularExpressions;\n\nnamespace VirtualSpace.Helpers\n{\n    public static class StringHelper\n    {\n        public static bool IsValidRegex( string pattern )\n        {\n            if ( string.IsNullOrWhiteSpace( pattern ) ) return false;\n\n            try\n            {\n                _ = Regex.Match( \"\", pattern );\n            }\n            catch ( ArgumentException )\n            {\n                return false;\n            }\n\n            return true;\n        }\n    }\n}"
  },
  {
    "path": "Helpers/SysInfo.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Diagnostics;\nusing System.Drawing;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Security.Principal;\nusing System.Windows.Forms;\nusing Microsoft.Win32;\nusing System.Management;\nusing System.Runtime.CompilerServices;\nusing System.Windows;\n\n[assembly: InternalsVisibleTo( \"ControlPanel\" )]\n\nnamespace VirtualSpace.Helpers\n{\n    public static class SysInfo\n    {\n        private const          int                          DefaultDpi = 96;\n        public static          (float ScaleX, float ScaleY) Dpi => GetDpi();\n        public static readonly bool                         IsWin10;\n        public static readonly bool                         IsAdministrator;\n\n        static SysInfo()\n        {\n            IsWin10 = Environment.OSVersion.Version is {Major: 10, Build: < 22000};\n            var windowsPrincipal = new WindowsPrincipal( WindowsIdentity.GetCurrent() );\n            IsAdministrator = windowsPrincipal.IsInRole( WindowsBuiltInRole.Administrator );\n        }\n\n        private static (float ScaleX, float ScaleY) GetDpi()\n        {\n            using var g = Graphics.FromHwnd( IntPtr.Zero );\n            return new ValueTuple<float, float>( g.DpiX / DefaultDpi, g.DpiY / DefaultDpi );\n        }\n\n        public static Version OSVersion\n        {\n            get\n            {\n                var winVer = Environment.OSVersion.Version;\n                if ( winVer.Revision == 0 )\n                {\n                    using var registryKey = Registry.LocalMachine.OpenSubKey( @\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\" );\n                    var       ubr         = registryKey?.GetValue( \"UBR\" );\n                    if ( ubr != null )\n                    {\n                        var buildNumber = int.Parse( ubr.ToString() );\n                        winVer = new Version( winVer.Major, winVer.Minor, winVer.Build, buildNumber );\n                    }\n                }\n\n                return winVer;\n            }\n        }\n\n        public static (int W, int H) GetAspectRadioOfScreen()\n        {\n            var nGCD = GetGreatestCommonDivisor( Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height );\n            return new ValueTuple<int, int>( Screen.PrimaryScreen.Bounds.Width / nGCD, Screen.PrimaryScreen.Bounds.Height / nGCD );\n        }\n\n        private static int GetGreatestCommonDivisor( int a, int b )\n        {\n            while ( true )\n            {\n                if ( b == 0 ) return a;\n                var a1 = a;\n                a = b;\n                b = a1 % b;\n            }\n        }\n\n        public static bool IsTaskbarVisible()\n        {\n            return Math.Abs( SystemParameters.PrimaryScreenHeight - SystemParameters.WorkArea.Height ) > 0;\n        }\n\n        public enum WinAppsTheme\n        {\n            LIGHT,\n            DARK\n        }\n\n        public static WinAppsTheme GetAppsTheme()\n        {\n            return WinRegistry.AppThemeIsLight() ? WinAppsTheme.LIGHT : WinAppsTheme.DARK;\n        }\n\n        private static RegValueMonitor _rkm = new( \"HKEY_USERS\",\n            @\"Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Themes\\\\Personalize\",\n            \"AppsUseLightTheme\" );\n\n        public static List<object> GetAllScreens()\n        {\n            var screens    = new List<object>();\n            var allScreens = Screen.AllScreens;\n            for ( var i = 0; i < allScreens.Length; i++ )\n            {\n                screens.Add( new {Value = i, Text = $\"{allScreens[i].DeviceName}  ({allScreens[i].DeviceFriendlyName()})\"} );\n            }\n\n            return screens;\n        }\n    }\n\n    /// <summary>\n    /// https://stackoverflow.com/questions/52875087/getting-device-friendly-name-incorrect-result\n    /// </summary>\n    public static class ScreenInterrogatory\n    {\n        private const int ERROR_SUCCESS = 0;\n\n        private static string MonitorFriendlyName( LUID adapterId, uint targetId )\n        {\n            var deviceName = new DISPLAYCONFIG_TARGET_DEVICE_NAME\n            {\n                header =\n                {\n                    size = (uint)Marshal.SizeOf( typeof( DISPLAYCONFIG_TARGET_DEVICE_NAME ) ),\n                    adapterId = adapterId,\n                    id = targetId,\n                    type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME\n                }\n            };\n            var error = DisplayConfigGetDeviceInfo( ref deviceName );\n            if ( error != ERROR_SUCCESS )\n                throw new Win32Exception( error );\n            return deviceName.monitorFriendlyDeviceName;\n        }\n\n        private static IEnumerable<string> GetAllMonitorsFriendlyNames()\n        {\n            var error = GetDisplayConfigBufferSizes(\n                QUERY_DEVICE_CONFIG_FLAGS.QDC_ONLY_ACTIVE_PATHS,\n                out var pathCount,\n                out var modeCount );\n\n            if ( error != ERROR_SUCCESS )\n                throw new Win32Exception( error );\n\n            var displayPaths = new DISPLAYCONFIG_PATH_INFO[pathCount];\n            var displayModes = new DISPLAYCONFIG_MODE_INFO[modeCount];\n\n            error = QueryDisplayConfig(\n                QUERY_DEVICE_CONFIG_FLAGS.QDC_ONLY_ACTIVE_PATHS,\n                ref pathCount,\n                displayPaths,\n                ref modeCount,\n                displayModes,\n                IntPtr.Zero );\n\n            if ( error != ERROR_SUCCESS )\n                throw new Win32Exception( error );\n\n            for ( var i = 0; i < modeCount; i++ )\n                if ( displayModes[i].infoType == DISPLAYCONFIG_MODE_INFO_TYPE.DISPLAYCONFIG_MODE_INFO_TYPE_TARGET )\n                    yield return MonitorFriendlyName( displayModes[i].adapterId, displayModes[i].id );\n        }\n\n        public static string DeviceFriendlyName( this Screen screen )\n        {\n            var allFriendlyNames = GetAllMonitorsFriendlyNames();\n            for ( var index = 0; index < Screen.AllScreens.Length; index++ )\n                if ( Equals( screen, Screen.AllScreens[index] ) )\n                    return allFriendlyNames.ToArray()[index];\n            return null;\n        }\n\n        #region enums\n\n        public enum QUERY_DEVICE_CONFIG_FLAGS : uint\n        {\n            QDC_ALL_PATHS         = 0x00000001,\n            QDC_ONLY_ACTIVE_PATHS = 0x00000002,\n            QDC_DATABASE_CURRENT  = 0x00000004\n        }\n\n        public enum DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY : uint\n        {\n            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER                = 0xFFFFFFFF,\n            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15                 = 0,\n            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SVIDEO               = 1,\n            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPOSITE_VIDEO      = 2,\n            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPONENT_VIDEO      = 3,\n            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DVI                  = 4,\n            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI                 = 5,\n            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_LVDS                 = 6,\n            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_D_JPN                = 8,\n            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDI                  = 9,\n            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL = 10,\n            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED = 11,\n            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EXTERNAL         = 12,\n            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED         = 13,\n            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDTVDONGLE           = 14,\n            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_MIRACAST             = 15,\n            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL             = 0x80000000,\n            DISPLAYCONFIG_OUTPUT_TECHNOLOGY_FORCE_UINT32         = 0xFFFFFFFF\n        }\n\n        public enum DISPLAYCONFIG_SCANLINE_ORDERING : uint\n        {\n            DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED                = 0,\n            DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE                = 1,\n            DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED                 = 2,\n            DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_UPPERFIELDFIRST = DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED,\n            DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_LOWERFIELDFIRST = 3,\n            DISPLAYCONFIG_SCANLINE_ORDERING_FORCE_UINT32               = 0xFFFFFFFF\n        }\n\n        private enum DISPLAYCONFIG_ROTATION : uint\n        {\n            DISPLAYCONFIG_ROTATION_IDENTITY     = 1,\n            DISPLAYCONFIG_ROTATION_ROTATE90     = 2,\n            DISPLAYCONFIG_ROTATION_ROTATE180    = 3,\n            DISPLAYCONFIG_ROTATION_ROTATE270    = 4,\n            DISPLAYCONFIG_ROTATION_FORCE_UINT32 = 0xFFFFFFFF\n        }\n\n        private enum DISPLAYCONFIG_SCALING : uint\n        {\n            DISPLAYCONFIG_SCALING_IDENTITY               = 1,\n            DISPLAYCONFIG_SCALING_CENTERED               = 2,\n            DISPLAYCONFIG_SCALING_STRETCHED              = 3,\n            DISPLAYCONFIG_SCALING_ASPECTRATIOCENTEREDMAX = 4,\n            DISPLAYCONFIG_SCALING_CUSTOM                 = 5,\n            DISPLAYCONFIG_SCALING_PREFERRED              = 128,\n            DISPLAYCONFIG_SCALING_FORCE_UINT32           = 0xFFFFFFFF\n        }\n\n        public enum DISPLAYCONFIG_PIXELFORMAT : uint\n        {\n            DISPLAYCONFIG_PIXELFORMAT_8BPP         = 1,\n            DISPLAYCONFIG_PIXELFORMAT_16BPP        = 2,\n            DISPLAYCONFIG_PIXELFORMAT_24BPP        = 3,\n            DISPLAYCONFIG_PIXELFORMAT_32BPP        = 4,\n            DISPLAYCONFIG_PIXELFORMAT_NONGDI       = 5,\n            DISPLAYCONFIG_PIXELFORMAT_FORCE_UINT32 = 0xffffffff\n        }\n\n        public enum DISPLAYCONFIG_MODE_INFO_TYPE : uint\n        {\n            DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE       = 1,\n            DISPLAYCONFIG_MODE_INFO_TYPE_TARGET       = 2,\n            DISPLAYCONFIG_MODE_INFO_TYPE_FORCE_UINT32 = 0xFFFFFFFF\n        }\n\n        public enum DISPLAYCONFIG_DEVICE_INFO_TYPE : uint\n        {\n            DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME           = 1,\n            DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME           = 2,\n            DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE = 3,\n            DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME          = 4,\n            DISPLAYCONFIG_DEVICE_INFO_SET_TARGET_PERSISTENCE    = 5,\n            DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_BASE_TYPE      = 6,\n            DISPLAYCONFIG_DEVICE_INFO_FORCE_UINT32              = 0xFFFFFFFF\n        }\n\n        #endregion\n\n        #region structs\n\n        [StructLayout( LayoutKind.Sequential )]\n        public struct LUID\n        {\n            public uint LowPart;\n            public int  HighPart;\n        }\n\n        [StructLayout( LayoutKind.Sequential )]\n        public struct DISPLAYCONFIG_PATH_SOURCE_INFO\n        {\n            public LUID adapterId;\n            public uint id;\n            public uint modeInfoIdx;\n            public uint statusFlags;\n        }\n\n        [StructLayout( LayoutKind.Sequential )]\n        public struct DISPLAYCONFIG_PATH_TARGET_INFO\n        {\n            public           LUID                                  adapterId;\n            public           uint                                  id;\n            public           uint                                  modeInfoIdx;\n            private readonly DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology;\n            private readonly DISPLAYCONFIG_ROTATION                rotation;\n            private readonly DISPLAYCONFIG_SCALING                 scaling;\n            private readonly DISPLAYCONFIG_RATIONAL                refreshRate;\n            private readonly DISPLAYCONFIG_SCANLINE_ORDERING       scanLineOrdering;\n            public           bool                                  targetAvailable;\n            public           uint                                  statusFlags;\n        }\n\n        [StructLayout( LayoutKind.Sequential )]\n        public struct DISPLAYCONFIG_RATIONAL\n        {\n            public uint Numerator;\n            public uint Denominator;\n        }\n\n        [StructLayout( LayoutKind.Sequential )]\n        public struct DISPLAYCONFIG_PATH_INFO\n        {\n            public DISPLAYCONFIG_PATH_SOURCE_INFO sourceInfo;\n            public DISPLAYCONFIG_PATH_TARGET_INFO targetInfo;\n            public uint                           flags;\n        }\n\n        [StructLayout( LayoutKind.Sequential )]\n        public struct DISPLAYCONFIG_2DREGION\n        {\n            public uint cx;\n            public uint cy;\n        }\n\n        [StructLayout( LayoutKind.Sequential )]\n        public struct DISPLAYCONFIG_VIDEO_SIGNAL_INFO\n        {\n            public ulong                           pixelRate;\n            public DISPLAYCONFIG_RATIONAL          hSyncFreq;\n            public DISPLAYCONFIG_RATIONAL          vSyncFreq;\n            public DISPLAYCONFIG_2DREGION          activeSize;\n            public DISPLAYCONFIG_2DREGION          totalSize;\n            public uint                            videoStandard;\n            public DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;\n        }\n\n        [StructLayout( LayoutKind.Sequential )]\n        public struct DISPLAYCONFIG_TARGET_MODE\n        {\n            public DISPLAYCONFIG_VIDEO_SIGNAL_INFO targetVideoSignalInfo;\n        }\n\n        [StructLayout( LayoutKind.Sequential )]\n        public struct POINTL\n        {\n            private readonly int x;\n            private readonly int y;\n        }\n\n        [StructLayout( LayoutKind.Sequential )]\n        public struct DISPLAYCONFIG_SOURCE_MODE\n        {\n            public uint                      width;\n            public uint                      height;\n            public DISPLAYCONFIG_PIXELFORMAT pixelFormat;\n            public POINTL                    position;\n        }\n\n        [StructLayout( LayoutKind.Explicit )]\n        public struct DISPLAYCONFIG_MODE_INFO_UNION\n        {\n            [FieldOffset( 0 )] public DISPLAYCONFIG_TARGET_MODE targetMode;\n\n            [FieldOffset( 0 )] public DISPLAYCONFIG_SOURCE_MODE sourceMode;\n        }\n\n        [StructLayout( LayoutKind.Sequential )]\n        public struct DISPLAYCONFIG_MODE_INFO\n        {\n            public DISPLAYCONFIG_MODE_INFO_TYPE  infoType;\n            public uint                          id;\n            public LUID                          adapterId;\n            public DISPLAYCONFIG_MODE_INFO_UNION modeInfo;\n        }\n\n        [StructLayout( LayoutKind.Sequential )]\n        public struct DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS\n        {\n            public uint value;\n        }\n\n        [StructLayout( LayoutKind.Sequential )]\n        public struct DISPLAYCONFIG_DEVICE_INFO_HEADER\n        {\n            public DISPLAYCONFIG_DEVICE_INFO_TYPE type;\n            public uint                           size;\n            public LUID                           adapterId;\n            public uint                           id;\n        }\n\n        [StructLayout( LayoutKind.Sequential, CharSet = CharSet.Unicode )]\n        public struct DISPLAYCONFIG_TARGET_DEVICE_NAME\n        {\n            public DISPLAYCONFIG_DEVICE_INFO_HEADER       header;\n            public DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS flags;\n            public DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY  outputTechnology;\n            public ushort                                 edidManufactureId;\n            public ushort                                 edidProductCodeId;\n            public uint                                   connectorInstance;\n\n            [MarshalAs( UnmanagedType.ByValTStr, SizeConst = 64 )]\n            public string monitorFriendlyDeviceName;\n\n            [MarshalAs( UnmanagedType.ByValTStr, SizeConst = 128 )]\n            public string monitorDevicePath;\n        }\n\n        #endregion\n\n        #region DLLImports\n\n        [DllImport( \"user32.dll\" )]\n        public static extern int GetDisplayConfigBufferSizes(\n            QUERY_DEVICE_CONFIG_FLAGS flags, out uint numPathArrayElements, out uint numModeInfoArrayElements );\n\n        [DllImport( \"user32.dll\" )]\n        public static extern int QueryDisplayConfig(\n            QUERY_DEVICE_CONFIG_FLAGS flags,\n            ref uint                  numPathArrayElements,     [Out] DISPLAYCONFIG_PATH_INFO[] PathInfoArray,\n            ref uint                  numModeInfoArrayElements, [Out] DISPLAYCONFIG_MODE_INFO[] ModeInfoArray,\n            IntPtr                    currentTopologyId\n        );\n\n        [DllImport( \"user32.dll\" )]\n        public static extern int DisplayConfigGetDeviceInfo( ref DISPLAYCONFIG_TARGET_DEVICE_NAME deviceName );\n\n        #endregion\n    }\n\n    public static class ProcessTools\n    {\n        public static string GetCommandLineArgs( this Process process )\n        {\n            if ( process is null ) throw new ArgumentNullException( nameof( process ) );\n\n            try\n            {\n                return GetCommandLineArgsCore();\n            }\n            catch\n            {\n                return string.Empty;\n            }\n\n            string GetCommandLineArgsCore()\n            {\n                using var searcher = new ManagementObjectSearcher( $\"SELECT CommandLine FROM Win32_Process WHERE ProcessId = {process.Id.ToString()}\" );\n                using var objects  = searcher.Get();\n                var       obj      = objects.Cast<ManagementBaseObject>().SingleOrDefault();\n                return obj?[\"CommandLine\"]?.ToString() ?? \"\";\n            }\n        }\n    }\n}"
  },
  {
    "path": "Helpers/TaskSchedulerHelper.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Diagnostics;\nusing Microsoft.Win32.TaskScheduler;\n\nnamespace VirtualSpace.Helpers\n{\n    public static class TaskSchedulerHelper\n    {\n        public static void CreateAutoRunTask( string taskName, string fullAppPath, string taskFolder = \"\" )\n        {\n            if ( !SysInfo.IsAdministrator )\n            {\n                throw new Exception( \"General.RunOnStartup.Error.Permission\" );\n            }\n\n            var td = TaskService.Instance.NewTask();\n            td.RegistrationInfo.Description = \"autorun \" + taskName + \" at system startup.\";\n            td.Principal.RunLevel = TaskRunLevel.Highest;\n            td.Principal.LogonType = TaskLogonType.InteractiveToken;\n            td.Settings.ExecutionTimeLimit = TimeSpan.FromSeconds( 0 );\n\n            var lt = new LogonTrigger();\n            lt.Delay = TimeSpan.FromSeconds( 5 );\n            td.Triggers.Add( lt );\n\n            var ea = new ExecAction( fullAppPath, \"\" );\n            td.Actions.Add( ea );\n\n            TaskService.Instance.RootFolder.RegisterTaskDefinition( GetTaskPath( taskName, taskFolder ), td );\n        }\n\n        public static void DeleteTaskByName( string taskName, string taskFolder = \"\" )\n        {\n            if ( !SysInfo.IsAdministrator )\n            {\n                throw new Exception( \"General.RunOnStartup.Error.Permission\" );\n            }\n\n            using var ts = new TaskService();\n            ts.RootFolder.DeleteTask( GetTaskPath( taskName, taskFolder ) );\n        }\n\n        public static bool IsTaskExistsByName( string taskName, string taskFolder = \"\" )\n        {\n            using var ts       = new TaskService();\n            var       t        = ts.GetTask( GetTaskPath( taskName, taskFolder ) );\n            return t != null;\n        }\n\n        private static string GetTaskPath( string taskName, string taskFolder )\n        {\n            return string.IsNullOrEmpty( taskFolder ) ? taskName : taskFolder + @\"\\\" + taskName;\n        }\n\n        public static void OpenWinTaskScheduler()\n        {\n            var psi = new ProcessStartInfo\n            {\n                FileName = \"taskschd.msc\",\n                UseShellExecute = true\n            };\n            Process.Start( psi );\n        }\n    }\n}"
  },
  {
    "path": "Helpers/User32.cs",
    "content": "﻿using System;\nusing System.Runtime.InteropServices;\nusing System.Text;\n\nnamespace VirtualSpace.Helpers\n{\n    public static class User32\n    {\n        public delegate bool EnumChildWindowsProc( IntPtr hWnd, int lParam );\n\n        public delegate bool EnumWindowsProc( IntPtr hWnd, int lParam );\n\n        public delegate IntPtr HookProc( int nCode, IntPtr wParam, IntPtr lParam );\n\n        [DllImport( \"user32.dll\", SetLastError = true )]\n        public static extern IntPtr FindWindow( string lpClassName, string lpWindowName );\n\n        [DllImport( \"user32.dll\", CharSet = CharSet.Auto )]\n        public static extern int GetWindowLong( IntPtr hWnd, int nIndex );\n\n        [DllImport( \"user32.dll\", SetLastError = true )]\n        public static extern IntPtr GetWindow( IntPtr hWnd, GetWindowType uCmd );\n\n        [DllImport( \"user32.dll\" )]\n        [return: MarshalAs( UnmanagedType.Bool )]\n        public static extern bool IsWindowEnabled( IntPtr hWnd );\n\n        [DllImport( \"user32.dll\", CharSet = CharSet.Auto )]\n        public static extern bool PostMessage( IntPtr hWnd, int msg, ulong wParam, ulong lParam );\n\n        [DllImport( \"user32.dll\", CharSet = CharSet.Auto )]\n        public static extern bool SendMessage( IntPtr hWnd, int msg, ulong wParam, ulong lParam );\n\n        public static IntPtr SetWindowLongPtr( HandleRef hWnd, int nIndex, int dwNewLong )\n        {\n            if ( IntPtr.Size == 8 )\n                return SetWindowLongPtr64( hWnd, nIndex, (IntPtr)dwNewLong );\n            else\n                return new IntPtr( SetWindowLong32( hWnd, nIndex, dwNewLong ) );\n        }\n\n        [DllImport( \"user32.dll\", EntryPoint = \"SetWindowLong\" )]\n        private static extern int SetWindowLong32( HandleRef hWnd, int nIndex, int dwNewLong );\n\n        [DllImport( \"user32.dll\", EntryPoint = \"SetWindowLongPtr\" )]\n        private static extern IntPtr SetWindowLongPtr64( HandleRef hWnd, int nIndex, IntPtr dwNewLong );\n\n        [DllImport( \"user32.dll\", CharSet = CharSet.Auto )]\n        public static extern int ShowWindow( IntPtr hWnd, short cmdShow );\n\n        [DllImport( \"user32.dll\" )]\n        public static extern int GetWindowText( IntPtr hWnd, StringBuilder buf, int nMaxCount );\n\n        [DllImport( \"user32.dll\", SetLastError = true, CharSet = CharSet.Auto )]\n        public static extern int GetClassName( IntPtr hWnd, StringBuilder lpClassName, int nMaxCount );\n\n        [DllImport( \"user32.dll\" )]\n        public static extern bool IsWindowVisible( IntPtr hWnd );\n\n        [DllImport( \"user32.dll\" )]\n        [return: MarshalAs( UnmanagedType.Bool )]\n        public static extern bool IsWindow( IntPtr hWnd );\n\n        [DllImport( \"user32.dll\" )]\n        public static extern bool IsIconic( IntPtr hWnd );\n\n        [DllImport( \"user32.dll\" )]\n        public static extern int EnumWindows( EnumWindowsProc func, int lParam );\n\n        [DllImport( \"user32.dll\" )]\n        [return: MarshalAs( UnmanagedType.Bool )]\n        public static extern bool EnumChildWindows( IntPtr hWndParent, EnumChildWindowsProc lpEnumFunc, int lParam );\n\n        [DllImport( \"user32.dll\" )]\n        public static extern IntPtr GetForegroundWindow();\n\n        [DllImport( \"user32.dll\" )]\n        [return: MarshalAs( UnmanagedType.Bool )]\n        public static extern bool SetForegroundWindow( IntPtr hWnd );\n\n        [DllImport( \"user32.dll\", SetLastError = true )]\n        public static extern bool BringWindowToTop( IntPtr hWnd );\n\n        [DllImport( \"user32.dll\", SetLastError = true )]\n        public static extern IntPtr SetParent( IntPtr hWndChild, IntPtr hWndNewParent );\n\n        [DllImport( \"user32.dll\" )]\n        public static extern int GetWindowThreadProcessId( IntPtr hWnd, out int processId );\n\n        [DllImport( \"user32.dll\", CharSet = CharSet.Auto, SetLastError = true )]\n        public static extern IntPtr SetWindowsHookEx( int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId );\n\n        [DllImport( \"user32.dll\", CharSet = CharSet.Auto, SetLastError = true )]\n        [return: MarshalAs( UnmanagedType.Bool )]\n        public static extern bool UnhookWindowsHookEx( IntPtr hhk );\n\n        [DllImport( \"user32.dll\", CharSet = CharSet.Auto, SetLastError = true )]\n        public static extern IntPtr CallNextHookEx( IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam );\n\n        [DllImport( \"user32.dll\" )]\n        public static extern short GetAsyncKeyState( int vKey );\n\n        [DllImport( \"user32.dll\" )]\n        public static extern short GetKeyState( int vKey );\n\n        [DllImport( \"user32.dll\", SetLastError = true )]\n        public static extern uint SendInput( uint numberOfInputs, INPUT[] inputs, int sizeOfInputStructure );\n\n        [DllImport( \"user32.dll\", CharSet = CharSet.Unicode )]\n        public static extern uint RegisterWindowMessage( string lpProcName );\n\n        [DllImport( \"user32.dll\" )]\n        public static extern bool GetWindowRect( IntPtr hWnd, ref RECT rectangle );\n\n        [DllImport( \"user32.dll\" )]\n        [return: MarshalAs( UnmanagedType.Bool )]\n        public static extern bool SetWindowPos( IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, SetWindowPosFlags uFlags );\n\n        [DllImport( \"user32.dll\", SetLastError = true )]\n        [return: MarshalAs( UnmanagedType.Bool )]\n        public static extern bool GetWindowPlacement( IntPtr hWnd, ref WINDOWPLACEMENT lpWndPl );\n\n        [DllImport( \"Shell32.dll\", SetLastError = false )]\n        public static extern int SHGetStockIconInfo( SHSTOCKICONID siid, SHGSI uFlags, ref SHSTOCKICONINFO psii );\n\n        [DllImport( \"user32.dll\", SetLastError = true )]\n        public static extern void SwitchToThisWindow( IntPtr hWnd, bool fAltTab );\n    }\n}"
  },
  {
    "path": "Helpers/UserMessage.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nnamespace VirtualSpace.Helpers\n{\n    public static class UserMessage\n    {\n        public const int RiseView                        = 1000;\n        public const int ShowAppController               = 1001;\n        public const int AppControllerClosed             = 1002;\n        public const int SwitchDesktop                   = 1003;\n        public const int DesktopArrangement              = 1004;\n        public const int RunAsAdministrator              = 1005;\n        public const int RestartApp                      = 1006;\n        public const int EnableMouseHook                 = 1007;\n        public const int DisableMouseHook                = 1008;\n        public const int RiseViewForActiveApp            = 1009;\n        public const int RestartAppController            = 1010;\n        public const int RiseViewForCurrentVD            = 1011;\n        public const int RiseViewForActiveAppInCurrentVD = 1012;\n        public const int RefreshVdw                      = 1013;\n        public const int SwitchBackToLastDesktop         = 1014;\n        public const int ShowVdw                         = 1015;\n        public const int ShowThumbsOfVdw                 = 1016;\n        public const int RefreshTrayIcon                 = 1017;\n        public const int UpdateTrayLang                  = 1018;\n        public const int ToggleWindowFilter              = 1019;\n\n        public const int NavLeft  = 1201;\n        public const int NavRight = 1202;\n        public const int NavUp    = 1203;\n        public const int NavDown  = 1204;\n\n        public static class Meta\n        {\n            public const int SVD_START = 1100;\n            public const int SVD_END   = 1200;\n            public const int MW_START  = 1300;\n            public const int MW_END    = 1400;\n            public const int MWF_START = 1500;\n            public const int MWF_END   = 1600;\n        }\n    }\n}"
  },
  {
    "path": "Helpers/VisualEffects.cs",
    "content": "﻿using System;\nusing System.Runtime.InteropServices;\n\nnamespace VirtualSpace.Helpers\n{\n    public static class VisualEffects\n    {\n        public enum AccentState\n        {\n            ACCENT_DISABLED                   = 0,\n            ACCENT_ENABLE_GRADIENT            = 1,\n            ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,\n            ACCENT_ENABLE_BLURBEHIND          = 3,\n            ACCENT_ENABLE_ACRYLICBLURBEHIND   = 4,\n            ACCENT_INVALID_STATE              = 5\n        }\n\n        public enum WindowCompositionAttribute\n        {\n            // ...\n            WCA_ACCENT_POLICY = 19\n            // ...\n        }\n\n        [DllImport( \"user32.dll\" )]\n        public static extern int SetWindowCompositionAttribute( IntPtr hWnd, ref WindowCompositionAttributeData data );\n\n        [StructLayout( LayoutKind.Sequential )]\n        public struct AccentPolicy\n        {\n            public AccentState AccentState;\n            public uint        AccentFlags;\n            public uint        GradientColor;\n            public uint        AnimationId;\n        }\n\n        [StructLayout( LayoutKind.Sequential )]\n        public struct WindowCompositionAttributeData\n        {\n            public WindowCompositionAttribute Attribute;\n            public IntPtr                     Data;\n            public int                        SizeOfData;\n        }\n    }\n}"
  },
  {
    "path": "Helpers/Win32.cs",
    "content": "﻿using System;\nusing System.Runtime.InteropServices;\n\nnamespace VirtualSpace.Helpers\n{\n    /// <summary>\n    ///     Contains information about the placement of a window on the screen.\n    /// </summary>\n    [Serializable]\n    [StructLayout( LayoutKind.Sequential )]\n    public struct WINDOWPLACEMENT\n    {\n        /// <summary>\n        ///     The length of the structure, in bytes. Before calling the GetWindowPlacement or SetWindowPlacement functions, set this member to sizeof(WINDOWPLACEMENT).\n        ///     <para>\n        ///         GetWindowPlacement and SetWindowPlacement fail if this member is not set correctly.\n        ///     </para>\n        /// </summary>\n        public int Length;\n\n        /// <summary>\n        ///     Specifies flags that control the position of the minimized window and the method by which the window is restored.\n        /// </summary>\n        public int Flags;\n\n        /// <summary>\n        ///     The current show state of the window.\n        /// </summary>\n        public ShowState ShowCmd;\n\n        /// <summary>\n        ///     The coordinates of the window's upper-left corner when the window is minimized.\n        /// </summary>\n        public POINT MinPosition;\n\n        /// <summary>\n        ///     The coordinates of the window's upper-left corner when the window is maximized.\n        /// </summary>\n        public POINT MaxPosition;\n\n        /// <summary>\n        ///     The window's coordinates when the window is in the restored position.\n        /// </summary>\n        public RECT NormalPosition;\n\n        /// <summary>\n        ///     Gets the default (empty) value.\n        /// </summary>\n        public static WINDOWPLACEMENT Default\n        {\n            get\n            {\n                var result = new WINDOWPLACEMENT();\n                result.Length = Marshal.SizeOf( result );\n                return result;\n            }\n        }\n    }\n\n    public enum ShowState : int\n    {\n        SW_HIDE            = 0,\n        SW_SHOWNORMAL      = 1,\n        SW_NORMAL          = 1,\n        SW_SHOWMINIMIZED   = 2,\n        SW_SHOWMAXIMIZED   = 3,\n        SW_MAXIMIZE        = 3,\n        SW_SHOWNOACTIVATE  = 4,\n        SW_SHOW            = 5,\n        SW_MINIMIZE        = 6,\n        SW_SHOWMINNOACTIVE = 7,\n        SW_SHOWNA          = 8,\n        SW_RESTORE         = 9,\n        SW_SHOWDEFAULT     = 10,\n        SW_FORCEMINIMIZE   = 11\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct RECT\n    {\n        public int Left;\n        public int Top;\n        public int Right;\n        public int Bottom;\n\n        public RECT( int left, int top, int right, int bottom )\n        {\n            Left = left;\n            Top = top;\n            Right = right;\n            Bottom = bottom;\n        }\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct SIZE\n    {\n        public int cx;\n        public int cy;\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct POINT\n    {\n        public int X;\n        public int Y;\n\n        public POINT( int x, int y )\n        {\n            X = x;\n            Y = y;\n        }\n    }\n\n    [Flags]\n    public enum WindowStyles : uint\n    {\n        WS_CHILD = 0x40000000\n    }\n\n    public enum GetWindowLongFields\n    {\n        GWL_USERDATA   = -21, // 0xFFFFFFEB\n        GWL_EXSTYLE    = -20, // 0xFFFFFFEC\n        GWL_STYLE      = -16, // 0xFFFFFFF0\n        GWL_ID         = -12, // 0xFFFFFFF4\n        GWL_HWNDPARENT = -8, // 0xFFFFFFF8\n        GWL_HINSTANCE  = -6, // 0xFFFFFFFA\n        GWL_WNDPROC    = -4 // 0xFFFFFFFC\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct INPUT\n    {\n        public InputType               Type;\n        public MOUSEKEYBDHARDWAREINPUT Data;\n    }\n\n    public enum InputType : uint\n    {\n        INPUT_MOUSE,\n        INPUT_KEYBOARD,\n        INPUT_HARDWARE\n    }\n\n    [StructLayout( LayoutKind.Explicit )]\n    public struct MOUSEKEYBDHARDWAREINPUT\n    {\n        [FieldOffset( 0 )] public HARDWAREINPUT Hardware;\n        [FieldOffset( 0 )] public KEYBDINPUT    Keyboard;\n        [FieldOffset( 0 )] public MOUSEINPUT    Mouse;\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct HARDWAREINPUT\n    {\n        public uint   Msg;\n        public ushort ParamL;\n        public ushort ParamH;\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct KEYBDINPUT\n    {\n        public ushort    Vk;\n        public ushort    Scan;\n        public KEYEVENTF Flags;\n        public uint      Time;\n        public IntPtr    ExtraInfo;\n    }\n\n    [Flags]\n    public enum KEYEVENTF : uint\n    {\n        EXTENDEDKEY = 0x0001,\n        KEYUP       = 0x0002,\n        SCANCODE    = 0x0008,\n        UNICODE     = 0x0004\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct MOUSEINPUT\n    {\n        public int    X;\n        public int    Y;\n        public uint   MouseData;\n        public uint   Flags;\n        public uint   Time;\n        public IntPtr ExtraInfo;\n    }\n\n    [Flags]\n    public enum SHGSI : uint\n    {\n        SHGSI_ICON      = 0x000000100,\n        SHGSI_SMALLICON = 0x000000001\n    }\n\n    public enum SHSTOCKICONID : uint\n    {\n        SIID_SHIELD = 77\n    }\n\n    [StructLayout( LayoutKind.Sequential, CharSet = CharSet.Unicode )]\n    public struct SHSTOCKICONINFO\n    {\n        public uint   cbSize;\n        public IntPtr hIcon;\n        public int    iSysIconIndex;\n        public int    iIcon;\n\n        [MarshalAs( UnmanagedType.ByValTStr, SizeConst = 260 )]\n        public string szPath;\n    }\n\n    public enum GetWindowType : uint\n    {\n        /// <summary>\n        /// The retrieved handle identifies the window of the same type that is highest in the Z order.\n        /// <para/>\n        /// If the specified window is a topmost window, the handle identifies a topmost window.\n        /// If the specified window is a top-level window, the handle identifies a top-level window.\n        /// If the specified window is a child window, the handle identifies a sibling window.\n        /// </summary>\n        GW_HWNDFIRST = 0,\n\n        /// <summary>\n        /// The retrieved handle identifies the window of the same type that is lowest in the Z order.\n        /// <para />\n        /// If the specified window is a topmost window, the handle identifies a topmost window.\n        /// If the specified window is a top-level window, the handle identifies a top-level window.\n        /// If the specified window is a child window, the handle identifies a sibling window.\n        /// </summary>\n        GW_HWNDLAST = 1,\n\n        /// <summary>\n        /// The retrieved handle identifies the window below the specified window in the Z order.\n        /// <para />\n        /// If the specified window is a topmost window, the handle identifies a topmost window.\n        /// If the specified window is a top-level window, the handle identifies a top-level window.\n        /// If the specified window is a child window, the handle identifies a sibling window.\n        /// </summary>\n        GW_HWNDNEXT = 2,\n\n        /// <summary>\n        /// The retrieved handle identifies the window above the specified window in the Z order.\n        /// <para />\n        /// If the specified window is a topmost window, the handle identifies a topmost window.\n        /// If the specified window is a top-level window, the handle identifies a top-level window.\n        /// If the specified window is a child window, the handle identifies a sibling window.\n        /// </summary>\n        GW_HWNDPREV = 3,\n\n        /// <summary>\n        /// The retrieved handle identifies the specified window's owner window, if any.\n        /// </summary>\n        GW_OWNER = 4,\n\n        /// <summary>\n        /// The retrieved handle identifies the child window at the top of the Z order,\n        /// if the specified window is a parent window; otherwise, the retrieved handle is NULL.\n        /// The function examines only child windows of the specified window. It does not examine descendant windows.\n        /// </summary>\n        GW_CHILD = 5,\n\n        /// <summary>\n        /// The retrieved handle identifies the enabled popup window owned by the specified window (the\n        /// search uses the first such window found using GW_HWNDNEXT); otherwise, if there are no enabled\n        /// popup windows, the retrieved handle is that of the specified window.\n        /// </summary>\n        GW_ENABLEDPOPUP = 6\n    }\n\n    /// <summary>\n    ///     Special window handles\n    /// </summary>\n    public enum SpecialWindowHandles\n    {\n        // ReSharper disable InconsistentNaming\n        /// <summary>\n        ///     Places the window at the top of the Z order.\n        /// </summary>\n        HWND_TOP = 0,\n\n        /// <summary>\n        ///     Places the window at the bottom of the Z order. If the hWnd parameter identifies a topmost window, the window loses its topmost status and is placed at the bottom of all other windows.\n        /// </summary>\n        HWND_BOTTOM = 1,\n\n        /// <summary>\n        ///     Places the window above all non-topmost windows. The window maintains its topmost position even when it is deactivated.\n        /// </summary>\n        HWND_TOPMOST = -1,\n\n        /// <summary>\n        ///     Places the window above all non-topmost windows (that is, behind all topmost windows). This flag has no effect if the window is already a non-topmost window.\n        /// </summary>\n        HWND_NOTOPMOST = -2\n        // ReSharper restore InconsistentNaming\n    }\n\n    [Flags]\n    public enum SetWindowPosFlags : uint\n    {\n        // ReSharper disable InconsistentNaming\n\n        /// <summary>\n        ///     If the calling thread and the thread that owns the window are attached to different input queues, the system posts the request to the thread that owns the window. This prevents the calling thread from blocking its execution while other threads process the request.\n        /// </summary>\n        SWP_ASYNCWINDOWPOS = 0x4000,\n\n        /// <summary>\n        ///     Prevents generation of the WM_SYNCPAINT message.\n        /// </summary>\n        SWP_DEFERERASE = 0x2000,\n\n        /// <summary>\n        ///     Draws a frame (defined in the window's class description) around the window.\n        /// </summary>\n        SWP_DRAWFRAME = 0x0020,\n\n        /// <summary>\n        ///     Applies new frame styles set using the SetWindowLong function. Sends a WM_NCCALCSIZE message to the window, even if the window's size is not being changed. If this flag is not specified, WM_NCCALCSIZE is sent only when the window's size is being changed.\n        /// </summary>\n        SWP_FRAMECHANGED = 0x0020,\n\n        /// <summary>\n        ///     Hides the window.\n        /// </summary>\n        SWP_HIDEWINDOW = 0x0080,\n\n        /// <summary>\n        ///     Does not activate the window. If this flag is not set, the window is activated and moved to the top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter parameter).\n        /// </summary>\n        SWP_NOACTIVATE = 0x0010,\n\n        /// <summary>\n        ///     Discards the entire contents of the client area. If this flag is not specified, the valid contents of the client area are saved and copied back into the client area after the window is sized or repositioned.\n        /// </summary>\n        SWP_NOCOPYBITS = 0x0100,\n\n        /// <summary>\n        ///     Retains the current position (ignores X and Y parameters).\n        /// </summary>\n        SWP_NOMOVE = 0x0002,\n\n        /// <summary>\n        ///     Does not change the owner window's position in the Z order.\n        /// </summary>\n        SWP_NOOWNERZORDER = 0x0200,\n\n        /// <summary>\n        ///     Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies to the client area, the nonclient area (including the title bar and scroll bars), and any part of the parent window uncovered as a result of the window being moved. When this flag is set, the application must explicitly invalidate or redraw any parts of the window and parent window that need redrawing.\n        /// </summary>\n        SWP_NOREDRAW = 0x0008,\n\n        /// <summary>\n        ///     Same as the SWP_NOOWNERZORDER flag.\n        /// </summary>\n        SWP_NOREPOSITION = 0x0200,\n\n        /// <summary>\n        ///     Prevents the window from receiving the WM_WINDOWPOSCHANGING message.\n        /// </summary>\n        SWP_NOSENDCHANGING = 0x0400,\n\n        /// <summary>\n        ///     Retains the current size (ignores the cx and cy parameters).\n        /// </summary>\n        SWP_NOSIZE = 0x0001,\n\n        /// <summary>\n        ///     Retains the current Z order (ignores the hWndInsertAfter parameter).\n        /// </summary>\n        SWP_NOZORDER = 0x0004,\n\n        /// <summary>\n        ///     Displays the window.\n        /// </summary>\n        SWP_SHOWWINDOW = 0x0040,\n    }\n}"
  },
  {
    "path": "Helpers/WinForms.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.Collections.Generic;\nusing System.Windows.Forms;\n\nnamespace VirtualSpace.Helpers\n{\n    public static class WinForms\n    {\n        private const string ComboBoxDisplayMember = \"Text\";\n        private const string ComboBoxValueMember   = \"Value\";\n\n        public static void SetComboBoxDataSource( ComboBox cbb,\n            List<object>                                   dataSource,\n            string                                         displayMember = ComboBoxDisplayMember,\n            string                                         valueMember   = ComboBoxValueMember )\n        {\n            cbb.DisplayMember = ComboBoxDisplayMember;\n            cbb.ValueMember = ComboBoxValueMember;\n            cbb.DataSource = dataSource;\n        }\n    }\n}"
  },
  {
    "path": "Helpers/WinMsg.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nnamespace VirtualSpace.Helpers\n{\n    public static class WinMsg\n    {\n        public const int WM_SYSCOMMAND    = 0x0112;\n        public const int SC_MAXIMIZE      = 0xF030;\n        public const int SC_MINIMIZE      = 0xF020;\n        public const int SC_RESTORE       = 0xF120;\n        public const int SC_SIZE          = 0xF000;\n        public const int SC_MOVE          = 0xF010;\n        public const int SC_CLOSE         = 0xF060;\n        public const int WM_HOTKEY        = 0x0312;\n        public const int WM_CLOSE         = 0x0010;\n        public const int WM_QUIT          = 0x0012;\n        public const int WM_DESTROY       = 0x0002;\n        public const int WM_MOUSEACTIVATE = 0x0021;\n        public const int MA_NOACTIVATE    = 0x3;\n    }\n}"
  },
  {
    "path": "Helpers/WinRegistry.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Drawing;\nusing System.Management;\nusing System.Security.Principal;\nusing Microsoft.Win32;\nusing VirtualSpace.AppLogs;\n\nnamespace VirtualSpace.Helpers\n{\n    public static class WinRegistry\n    {\n        private const string PATH_VD_WALLPAPER_REGISTRY = @\"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VirtualDesktops\\Desktops\\\";\n        private const string PATH_WALLPAPER_REGISTRY    = @\"HKEY_CURRENT_USER\\Control Panel\\Desktop\\\";\n        private const string PATH_COLOR_REGISTRY        = @\"HKEY_CURRENT_USER\\Control Panel\\Colors\\\";\n        private const string PATH_APP_USE_LIGHT_THEME   = @\"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize\\\";\n\n        public static Wallpaper GetWallpaperByDesktopGuid( Guid guid, int width, int height, string cachePath, long quality )\n        {\n            var wallpaper = new Wallpaper();\n\n            var path = GetWallPaperPathByGuid( guid );\n\n            if ( string.IsNullOrEmpty( path ) )\n            {\n                wallpaper.Color = GetBackColor();\n            }\n            else\n            {\n                wallpaper.Image = Images.GetScaledBitmap( width, height, path, ref wallpaper, cachePath, quality );\n            }\n\n            return wallpaper;\n        }\n\n        public static Wallpaper GetWallpaperByPath( string path, int width, int height, string cachePath, long quality )\n        {\n            var wallpaper = new Wallpaper();\n            wallpaper.Image = Images.GetScaledBitmap( width, height, path, ref wallpaper, cachePath, quality );\n            return wallpaper;\n        }\n\n        public static string? GetDefaultWallpaperPath()\n        {\n            return Registry.GetValue( PATH_WALLPAPER_REGISTRY, \"Wallpaper\", \"\" ).ToString();\n        }\n\n        public static string? GetWallPaperPathByGuid( Guid guid )\n        {\n            var path = Registry.GetValue( PATH_VD_WALLPAPER_REGISTRY + \"{\" + guid + \"}\", \"Wallpaper\", \"\" )?.ToString();\n\n            if ( string.IsNullOrEmpty( path ) )\n                path = GetDefaultWallpaperPath();\n\n            return string.IsNullOrEmpty( path ) ? null : path;\n        }\n\n        public static Color GetBackColor()\n        {\n            var color    = Registry.GetValue( PATH_COLOR_REGISTRY, \"Background\", \"\" ).ToString();\n            var strColor = color.Split( ' ' );\n            return Color.FromArgb( int.Parse( strColor[0] ), int.Parse( strColor[1] ), int.Parse( strColor[2] ) );\n        }\n\n        public static bool AppThemeIsLight()\n        {\n            return Registry.GetValue( PATH_APP_USE_LIGHT_THEME, \"AppsUseLightTheme\", \"1\" ).ToString() == \"1\";\n        }\n    }\n\n    public class RegValueMonitor : IDisposable\n    {\n        private readonly ManagementEventWatcher? _watcher;\n\n        public RegValueMonitor( string hive, string keyPath, string valueName )\n        {\n            var currentUser = WindowsIdentity.GetCurrent();\n            var sid         = currentUser.User.Value;\n            var q = $\"SELECT * FROM RegistryValueChangeEvent WHERE Hive='{hive}' \" +\n                    @$\"AND KeyPath='{sid}\\\\{keyPath}' AND ValueName='{valueName}'\";\n\n            var query = new WqlEventQuery( q );\n            try\n            {\n                _watcher = new ManagementEventWatcher( query );\n                _watcher.EventArrived += HandleEvent;\n                _watcher.Start();\n            }\n            catch ( ManagementException managementException )\n            {\n                Logger.Error( \"[Registry]: \" + managementException.Message );\n            }\n        }\n\n        private static void HandleEvent( object sender, EventArrivedEventArgs e )\n        {\n            var keyPath   = e.NewEvent.Properties[\"Hive\"].Value + @\"\\\" + e.NewEvent.Properties[\"KeyPath\"].Value;\n            var valueName = e.NewEvent.Properties[\"ValueName\"].Value.ToString();\n\n            var v = Registry.GetValue( keyPath, valueName, \"\" );\n            OnRegValueChanged?.Invoke( null, new RegValueChangedEventArgs( v.ToString() ) );\n        }\n\n        public void Dispose()\n        {\n            _watcher?.Stop();\n        }\n\n        public static event EventHandler<RegValueChangedEventArgs>? OnRegValueChanged;\n\n        public class RegValueChangedEventArgs : EventArgs\n        {\n            public string Value { get; set; }\n\n            public RegValueChangedEventArgs( string value )\n            {\n                Value = value;\n            }\n        }\n    }\n}"
  },
  {
    "path": "Ipc/Commons/Config.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nnamespace VirtualSpace.Commons\n{\n    public static class Config\n    {\n        public const string PIPE_NAME   = \"VIRTUAL_SPACE_IPC_PIPE\";\n        public const string PIPE_SERVER = \".\";\n    }\n}"
  },
  {
    "path": "Ipc/Commons/HostInfo.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Diagnostics;\nusing System.Reflection;\n\nnamespace VirtualSpace.Commons\n{\n    public class HostInfo\n    {\n        public Version Version          { get; set; }\n        public string  Product          { get; set; }\n        public string  InfoVersion      { get; set; }\n        public string  AppPath          { get; set; }\n        public int     MainWindowHandle { get; set; }\n    }\n\n    public static class HostInfoHelper\n    {\n        public static HostInfo GetHostInfo()\n        {\n            var entryAssembly = Assembly.GetEntryAssembly();\n\n            var product = ( (AssemblyProductAttribute)Attribute.GetCustomAttribute(\n                entryAssembly,\n                typeof( AssemblyProductAttribute ),\n                false ) ).Product;\n\n            var fileVersion = ( (AssemblyFileVersionAttribute)Attribute.GetCustomAttribute(\n                entryAssembly,\n                typeof( AssemblyFileVersionAttribute ),\n                false ) ).Version;\n\n            var infoVersion = ( (AssemblyInformationalVersionAttribute)Attribute.GetCustomAttribute(\n                entryAssembly,\n                typeof( AssemblyInformationalVersionAttribute ),\n                false ) ).InformationalVersion;\n\n            return new HostInfo\n            {\n                Version = new Version( fileVersion ),\n                Product = product,\n                InfoVersion = infoVersion,\n                AppPath = Process.GetCurrentProcess().MainModule.FileName\n            };\n        }\n    }\n}"
  },
  {
    "path": "Ipc/Commons/Ipc.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFrameworks>net6.0-windows</TargetFrameworks>\n        <Nullable>enable</Nullable>\n        <LangVersion>9</LangVersion>\n    </PropertyGroup>\n\n</Project>\n"
  },
  {
    "path": "Ipc/Commons/PipeMessage.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Runtime.InteropServices;\n\nnamespace VirtualSpace.Commons\n{\n    public class PipeMessage\n    {\n        public PipeMessageType Type      { get; set; }\n        public int             Handle    { get; set; }\n        public int             ProcessId { get; set; }\n        public string          Name      { get; set; }\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct COPYDATASTRUCT\n    {\n        public IntPtr dwData;\n        public int    cbData;\n        public IntPtr lpData;\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct VirtualDesktopSwitchInfo\n    {\n        public IntPtr hostHandle;\n        public int    vdCount;\n        public int    fromIndex;\n        public int    dir;\n        public int    targetIndex;\n    }\n}"
  },
  {
    "path": "Ipc/Commons/PipeMessageType.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nnamespace VirtualSpace.Commons\n{\n    public enum PipeMessageType\n    {\n        INSTANCE,\n        PLUGIN_VD_SWITCH_OBSERVER,\n        PLUGIN_CHECK_ALIVE,\n        PLUGIN_UPDATER,\n        RESTART\n    }\n}"
  },
  {
    "path": "Ipc/IpcClient/IpcClient.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFrameworks>net6.0-windows</TargetFrameworks>\n        <Nullable>enable</Nullable>\n        <LangVersion>9</LangVersion>\n    </PropertyGroup>\n\n    <ItemGroup>\n      <ProjectReference Include=\"..\\Commons\\Ipc.csproj\" />\n    </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "Ipc/IpcClient/IpcPipeClient.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Diagnostics;\nusing System.IO;\nusing System.IO.Pipes;\nusing System.Text.Json;\nusing System.Threading.Tasks;\n\nnamespace VirtualSpace.Commons\n{\n    public static class IpcPipeClient\n    {\n        private const string PIPE_NAME   = Config.PIPE_NAME;\n        private const string PIPE_SERVER = Config.PIPE_SERVER;\n\n        private static bool CheckIn( PipeMessage pipeMessage )\n        {\n            using var client = new NamedPipeClientStream( PIPE_SERVER, PIPE_NAME, PipeDirection.InOut, PipeOptions.None );\n            try\n            {\n                client.Connect( 1000 );\n                if ( client.IsConnected )\n                {\n                    using var writer = new StreamWriter( client );\n                    writer.WriteLine( JsonSerializer.Serialize( pipeMessage ) );\n                    writer.Flush();\n\n                    return true;\n                }\n            }\n            catch\n            {\n                // ignored\n            }\n\n            return false;\n        }\n\n        private static bool CheckInAndWaitResponse<T>( PipeMessage pipeMessage, Action<T> callback )\n        {\n            using var client = new NamedPipeClientStream( PIPE_SERVER, PIPE_NAME, PipeDirection.InOut, PipeOptions.None );\n            try\n            {\n                client.Connect( 1000 );\n                if ( client.IsConnected )\n                {\n                    using var reader = new StreamReader( client );\n                    using var writer = new StreamWriter( client );\n                    writer.WriteLine( JsonSerializer.Serialize( pipeMessage ) );\n                    writer.Flush();\n\n                    var line = reader.ReadLine();\n                    callback( JsonSerializer.Deserialize<T>( line ) );\n\n                    return true;\n                }\n            }\n            catch\n            {\n                // ignored\n            }\n\n            return false;\n        }\n\n        private static bool AskAlive( string name, int handle, int pId )\n        {\n            using var client = new NamedPipeClientStream( PIPE_SERVER, PIPE_NAME, PipeDirection.InOut, PipeOptions.None );\n            try\n            {\n                client.Connect( 1000 );\n                if ( client.IsConnected )\n                {\n                    var       msg    = new PipeMessage {Type = PipeMessageType.PLUGIN_CHECK_ALIVE, Handle = handle, ProcessId = pId, Name = name};\n                    using var writer = new StreamWriter( client );\n                    writer.WriteLine( JsonSerializer.Serialize( msg ) );\n                    writer.Flush();\n\n                    return true;\n                }\n            }\n            catch\n            {\n                // ignored\n            }\n\n            return false;\n        }\n\n        public static async void CheckAlive( string name, int handle, int pId, int interval, Action exit )\n        {\n            while ( AskAlive( name, handle, pId ) )\n            {\n                await Task.Delay( interval * 1000 );\n            }\n\n            exit();\n        }\n\n        public static void PluginCheckIn( PipeMessage pipeMessage, Action error, Action exit )\n        {\n            var pId = Process.GetCurrentProcess().Id;\n            pipeMessage.ProcessId = pId;\n\n            if ( CheckIn( pipeMessage ) ) return;\n\n            error();\n            exit();\n        }\n\n        public static void PluginCheckIn<T>( PipeMessage pipeMessage, Action error, Action exit, Action<T> callback )\n        {\n            var pId = Process.GetCurrentProcess().Id;\n            pipeMessage.ProcessId = pId;\n\n            if ( CheckInAndWaitResponse<T>( pipeMessage, callback ) ) return;\n\n            error();\n            exit();\n        }\n\n        public static void NotifyHostRestart()\n        {\n            using var client = new NamedPipeClientStream( PIPE_SERVER, PIPE_NAME, PipeDirection.InOut, PipeOptions.None );\n            try\n            {\n                client.Connect( 1000 );\n                if ( client.IsConnected )\n                {\n                    using var writer = new StreamWriter( client );\n                    writer.WriteLine( JsonSerializer.Serialize( new PipeMessage {Type = PipeMessageType.RESTART} ) );\n                    writer.Flush();\n                }\n            }\n            catch\n            {\n                // ignored\n            }\n        }\n    }\n}"
  },
  {
    "path": "Ipc/IpcServer/IpcPipeServer.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.IO;\nusing System.IO.Pipes;\nusing System.Linq;\nusing System.Text.Json;\nusing System.Threading.Tasks;\nusing VirtualSpace.AppLogs;\nusing VirtualSpace.Helpers;\nusing VirtualSpace.Plugin;\n\nnamespace VirtualSpace.Commons\n{\n    public static class IpcPipeServer\n    {\n        private const  string PIPE_NAME   = Config.PIPE_NAME;\n        private const  string PIPE_SERVER = Config.PIPE_SERVER;\n        private static bool   _isRunning  = true;\n        public static  IntPtr MainWindowHandle { get; set; }\n\n        public static void Start()\n        {\n            Task.Factory.StartNew( () =>\n            {\n                Logger.Info( \"Ipc Pipe Server Wait For Connections.\" );\n\n                while ( _isRunning )\n                {\n                    using var server = new NamedPipeServerStream( PIPE_NAME );\n                    server.WaitForConnection();\n                    using var reader = new StreamReader( server );\n                    var       line   = reader.ReadLine();\n\n                    if ( !string.IsNullOrEmpty( line ) )\n                    {\n                        MessageProcessing( line, server );\n                    }\n                }\n                Logger.Info( \"Ipc Pipe Server Shutdown.\" );\n                \n            }, TaskCreationOptions.LongRunning );\n            \n            return;\n\n            void MessageProcessing( string line, NamedPipeServerStream server )\n            {\n                var msg = JsonSerializer.Deserialize<PipeMessage>( line );\n                switch ( msg?.Type )\n                {\n                    case PipeMessageType.INSTANCE:\n                        Logger.Info( \"Only single instance allowed, just bring to top.\" );\n                        User32.PostMessage( MainWindowHandle, WinMsg.WM_HOTKEY, UserMessage.RiseView, 0 );\n                        break;\n\n                    case PipeMessageType.PLUGIN_VD_SWITCH_OBSERVER:\n                    {\n                        if ( !server.CanWrite ) break;\n                        using var writer   = new StreamWriter( server );\n                        var       hostInfo = HostInfoHelper.GetHostInfo();\n                        hostInfo.MainWindowHandle = MainWindowHandle.ToInt32();\n                        writer.WriteLine( JsonSerializer.Serialize( hostInfo ) );\n                        writer.Flush();\n\n                        /////////////////////////////////\n                        // 只接受已注册成功的插件\n                        // 同时若插件名相同，则后启动的覆盖先启动的\n                        foreach ( var p in PluginHost.Plugins.Where( p => p.Name == msg.Name ) )\n                        {\n                            Logger.Info( $\"[PLUGIN\\\\Virtual Desktop Switch Observer] {p.Display} Started.\" );\n                            p.Handle    = (IntPtr)msg.Handle;\n                            p.ProcessId = msg.ProcessId;\n                            p.Type      = PluginType.VD_SWITCH_OBSERVER;\n                            break;\n                        }\n\n                        break;\n                    }\n\n                    case PipeMessageType.PLUGIN_CHECK_ALIVE:\n                    {\n                        var runningPlugin = PluginHost.Plugins.Find( p =>\n                            p.Name == msg.Name\n                            && p.Handle == (IntPtr)msg.Handle\n                            && p.ProcessId == msg.ProcessId );\n\n                        ////////////////////////////////////////////////\n                        // 若插件提供的信息在宿主中查不到，就通知该插件自行关闭\n                        // 这通常是因为有同名插件启动，覆盖了先启动的插件的信息\n                        if ( runningPlugin == null )\n                        {\n                            PluginHost.ClosePlugin( new PluginInfo {Handle = (IntPtr)msg.Handle} );\n                        }\n\n                        break;\n                    }\n\n                    case PipeMessageType.PLUGIN_UPDATER:\n                    {\n                        if ( !server.CanWrite ) break;\n                        using var writer = new StreamWriter( server );\n                        writer.WriteLine( JsonSerializer.Serialize( HostInfoHelper.GetHostInfo() ) );\n                        writer.Flush();\n\n                        foreach ( var p in PluginHost.Plugins.Where( p => p.Name == msg.Name ) )\n                        {\n                            Logger.Info( $\"[PLUGIN\\\\App Updater] {p.Display} Started.\" );\n                            p.Handle    = (IntPtr)msg.Handle;\n                            p.ProcessId = msg.ProcessId;\n                            p.Type      = PluginType.UPDATER;\n                            break;\n                        }\n\n                        break;\n                    }\n\n                    case PipeMessageType.RESTART:\n                    {\n                        User32.PostMessage( MainWindowHandle, WinMsg.WM_HOTKEY, UserMessage.RestartApp, 0 );\n                        break;\n                    }\n\n                    default:\n                        break;\n                }\n            }\n        }\n\n        public static void AsClient()\n        {\n            using var client = new NamedPipeClientStream( PIPE_SERVER, PIPE_NAME, PipeDirection.InOut, PipeOptions.None );\n            try\n            {\n                client.Connect( 3000 );\n                using var writer = new StreamWriter( client );\n                var       msg    = new PipeMessage {Type = PipeMessageType.INSTANCE};\n                writer.WriteLine( JsonSerializer.Serialize( msg ) );\n                writer.Flush();\n            }\n            catch\n            {\n                // ignored\n            }\n        }\n\n        public static void SimpleShutdown()\n        {\n            _isRunning = false;\n            foreach ( var pluginInfo in PluginHost.Plugins )\n            {\n                PluginHost.ClosePlugin( pluginInfo );\n            }\n\n            using var client = new NamedPipeClientStream( PIPE_SERVER, PIPE_NAME, PipeDirection.InOut, PipeOptions.None );\n            try\n            {\n                client.Connect( 10 );\n                client.Close();\n            }\n            catch\n            {\n                // ignored\n            }\n        }\n    }\n}"
  },
  {
    "path": "Ipc/IpcServer/IpcServer.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFrameworks>net6.0-windows</TargetFrameworks>\n        <Nullable>enable</Nullable>\n        <LangVersion>9</LangVersion>\n    </PropertyGroup>\n\n    <ItemGroup>\n        <ProjectReference Include=\"..\\..\\Helpers\\Helpers.csproj\" />\n        <ProjectReference Include=\"..\\..\\Plugin\\PluginHost\\PluginHost.csproj\" />\n        <ProjectReference Include=\"..\\Commons\\Ipc.csproj\" />\n    </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "LinqExpressionBuilder/COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "LinqExpressionBuilder/Keywords.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of LinqExpressionBuilder.\n\nLinqExpressionBuilder is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nLinqExpressionBuilder is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with LinqExpressionBuilder. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nnamespace LinqExpressionBuilder\n{\n    public static class Keywords\n    {\n        public const           string   String       = \"string\";\n        public const           string   V            = nameof( V );\n        public const           string   L            = nameof( L );\n        public static readonly string   Operator     = nameof( Operator ).ToLower();\n        public static readonly string   Type         = nameof( Type ).ToLower();\n        public static readonly string   Field        = nameof( Field ).ToLower();\n        public static readonly string   Value        = nameof( Value ).ToLower();\n        public static readonly string[] Eq           = {\"=\", \"is\", \"==\", \"eq\", \"equal\", \"equals\"};\n        public static readonly string[] In           = {\"in\", \"∈\"};\n        public static readonly string[] StartsWith   = {\"ssw\", \"starts with\", \"|-\"};\n        public static readonly string[] EndsWith     = {\"esw\", \"ends with\", \"-|\"};\n        public static readonly string[] Contains     = {\"sc\", \"contains\", \"∋\"};\n        public static readonly string[] RegexIsMatch = {\"rim\", \"regex\", \"/r/\"};\n        public static readonly string   Condition    = nameof( Condition ).ToLower();\n        public static readonly string   And          = nameof( And ).ToLower();\n        public static readonly string   Or           = nameof( Or ).ToLower();\n        public static readonly string   Rules        = nameof( Rules ).ToLower();\n        public static readonly string   Boolean      = nameof( Boolean ).ToLower();\n        public static readonly string   Number       = nameof( Number ).ToLower();\n        public static readonly string   Id           = nameof( Id ).ToLower();\n    }\n}"
  },
  {
    "path": "LinqExpressionBuilder/LinqExpressionBuilder.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of LinqExpressionBuilder.\n\nLinqExpressionBuilder is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nLinqExpressionBuilder is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with LinqExpressionBuilder. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Linq;\nusing System.Linq.Expressions;\nusing System.Reflection;\nusing System.Text.Json;\nusing System.Text.RegularExpressions;\n\nnamespace LinqExpressionBuilder\n{\n    public class JsonParser\n    {\n        private readonly MethodInfo _listContains = typeof( Enumerable )\n            .GetMethods( BindingFlags.Static | BindingFlags.Public )\n            .Single( m =>\n                m.Name == nameof( Enumerable.Contains )\n                && m.GetParameters().Length == 2 );\n\n        private readonly MethodInfo? _regexIsMatch  = typeof( Regex ).GetMethod( nameof( Regex.IsMatch ), new Type[] {typeof( string ), typeof( string )} );\n        private readonly MethodInfo? _strContains   = typeof( string ).GetMethod( nameof( string.Contains ), new Type[] {typeof( string )} );\n        private readonly MethodInfo? _strEndsWith   = typeof( string ).GetMethod( nameof( string.EndsWith ), new Type[] {typeof( string )} );\n        private readonly MethodInfo? _strStartsWith = typeof( string ).GetMethod( nameof( string.StartsWith ), new Type[] {typeof( string )} );\n\n        private Expression? ParseTree( JsonElement condition, ParameterExpression param )\n        {\n            if ( condition.TryGetProperty( Keywords.Condition, out var combine ) )\n            {\n                var    gate = condition.GetProperty( Keywords.Condition ).GetString();\n                Binder binder;\n\n                if ( gate == Keywords.And )\n                    binder = Expression.And;\n                else\n                    binder = Expression.Or;\n\n                Expression? Bind( Expression? l, Expression? r )\n                {\n                    return l == null ? r : binder( l, r );\n                }\n\n                Expression? left  = null;\n                var         rules = condition.GetProperty( Keywords.Rules );\n                foreach ( var rule in rules.EnumerateArray() )\n                {\n                    if ( rule.TryGetProperty( Keywords.Condition, out var nested ) )\n                    {\n                        left = Bind( left, ParseTree( rule, param ) );\n                    }\n                    else\n                    {\n                        left = Bind( left, SimpleCondition( rule, param ) );\n                    }\n                }\n\n                return left;\n            }\n\n            return SimpleCondition( condition, param );\n        }\n\n        private Expression? SimpleCondition( JsonElement rule, ParameterExpression param )\n        {\n            var @operator = rule.GetProperty( Keywords.Operator ).GetString().ToLower();\n            var type      = rule.GetProperty( Keywords.Type ).GetString().ToLower();\n            var field     = rule.GetProperty( Keywords.Field ).GetString();\n            var value     = rule.GetProperty( Keywords.Value );\n\n            var V = value.GetProperty( Keywords.In.Contains( @operator ) ? Keywords.L : Keywords.V );\n\n            var    property = Expression.Property( param, field );\n            object target;\n\n            Expression? right = default;\n\n            if ( Keywords.Eq.Contains( @operator ) )\n            {\n                if ( type == Keywords.String || type == Keywords.Boolean )\n                    target = V.GetString();\n                else\n                    target = V.GetDecimal();\n                var toCompare = Expression.Constant( target );\n                right = Expression.Equal( property, toCompare );\n            }\n            else if ( Keywords.In.Contains( @operator ) )\n            {\n                var listContains = _listContains.MakeGenericMethod( typeof( string ) );\n                target = V.EnumerateArray().Select( e => e.GetString() ).ToList();\n                right = Expression.Call(\n                    listContains,\n                    Expression.Constant( target ),\n                    property );\n            }\n            else if ( Keywords.StartsWith.Contains( @operator ) )\n            {\n                right = Expression.Call(\n                    property,\n                    _strStartsWith,\n                    Expression.Constant( V.GetString() )\n                );\n            }\n            else if ( Keywords.EndsWith.Contains( @operator ) )\n            {\n                right = Expression.Call(\n                    property,\n                    _strEndsWith,\n                    Expression.Constant( V.GetString() )\n                );\n            }\n            else if ( Keywords.Contains.Contains( @operator ) )\n            {\n                right = Expression.Call(\n                    property,\n                    _strContains,\n                    Expression.Constant( V.GetString() )\n                );\n            }\n            else if ( Keywords.RegexIsMatch.Contains( @operator ) )\n            {\n                right = Expression.Call(\n                    _regexIsMatch,\n                    property,\n                    Expression.Constant( V.GetString() )\n                );\n            }\n\n            return right;\n        }\n\n        private Expression<Func<T, bool>> BuildPredicate<T>( JsonDocument doc )\n        {\n            var itemTypeExpr = Expression.Parameter( typeof( T ) );\n            var conditions   = ParseTree( doc.RootElement, itemTypeExpr );\n            if ( conditions.CanReduce )\n            {\n                conditions = conditions.ReduceAndCheck();\n            }\n\n            return Expression.Lambda<Func<T, bool>>( conditions, itemTypeExpr );\n        }\n\n        public Func<T, bool> ExpressionFromJsonDoc<T>( JsonDocument doc )\n        {\n            return BuildPredicate<T>( doc ).Compile();\n        }\n\n        private delegate Expression? Binder( Expression left, Expression right );\n    }\n}"
  },
  {
    "path": "LinqExpressionBuilder/LinqExpressionBuilder.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFrameworks>net6.0-windows</TargetFrameworks>\n        <Nullable>enable</Nullable>\n        <LangVersion>9</LangVersion>\n    </PropertyGroup>\n\n</Project>\n"
  },
  {
    "path": "Logger/COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "Logger/LogMessage.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nnamespace VirtualSpace.AppLogs\n{\n    public class LogMessage\n    {\n        public string Type    { get; set; }\n        public string Message { get; set; }\n\n        public static LogMessage CreateMessage( string type, string msg )\n        {\n            return new LogMessage\n            {\n                Type = type,\n                Message = msg\n            };\n        }\n    }\n}"
  },
  {
    "path": "Logger/Logger.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Runtime.InteropServices;\nusing System.Text;\nusing System.Threading.Channels;\nusing System.Windows.Media;\nusing Notification.Wpf;\nusing Notification.Wpf.Constants;\n\nnamespace VirtualSpace.AppLogs\n{\n    public static class Logger\n    {\n        public static readonly Channel<LogMessage> LogChannel = Channel.CreateUnbounded<LogMessage>();\n        public static          bool                ShowLogsInGui { get; set; } = false;\n\n        public static void Verbose( string str )\n        {\n            LogToGui( \"VERBOSE\", str );\n            LogManager.RootLogger.Verbose( str );\n        }\n\n        public static void Debug( string str )\n        {\n            LogToGui( \"DEBUG\", str );\n            LogManager.RootLogger.Debug( str );\n        }\n\n        public static void Event( string str )\n        {\n            LogToGui( \"EVENT\", str );\n            LogManager.RootLogger.Write( LogManager.LOG_LEVEL_EVENT, str );\n        }\n\n        public static void Info( string str )\n        {\n            LogToGui( \"INFO\", str );\n            LogManager.RootLogger.Information( str );\n        }\n\n        public static void Warning( string str )\n        {\n            LogToGui( \"WARNING\", str );\n            LogManager.RootLogger.Warning( str );\n        }\n\n        public static void Error( string str, NotifyObject? notify = null )\n        {\n            LogToGui( \"ERROR\", str );\n            LogManager.RootLogger.Error( str );\n            if ( notify != null )\n            {\n                notify.Background = new SolidColorBrush( Colors.DarkRed );\n                notify.Foreground = new SolidColorBrush( Colors.White );\n                notify.Type = NotificationType.Error;\n                Notify( notify );\n            }\n        }\n\n        private static async void LogToGui( string type, string str )\n        {\n            if ( !ShowLogsInGui ) return;\n            var logMessage = LogMessage.CreateMessage(\n                type,\n                $\"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}][{type}] {str} {{ThreadId:{Environment.CurrentManagedThreadId.ToString()}}}\\r\\n\" );\n            await LogChannel.Writer.WriteAsync( logMessage ).ConfigureAwait( false );\n        }\n\n        public static void Notify( NotifyObject no )\n        {\n            var notificationManager = new NotificationManager();\n            var content = new NotificationContent\n            {\n                Title = no.Title,\n                Message = no.Message,\n                Type = no.Type,\n                TrimType = NotificationTextTrimType.NoTrim, // will show attach button on message\n                RowsCount = 5, // Will show 5 rows and trim after\n                LeftButtonContent = \"\", // Left button content (string or what u want\n                RightButtonContent = \"\", // Right button content (string or what u want\n                CloseOnClick = true // Set true if u want close message when left mouse button click on message (base = true)\n            };\n\n            if ( no.Background != null )\n            {\n                content.Background = no.Background;\n            }\n\n            if ( no.Foreground != null )\n            {\n                content.Foreground = no.Foreground;\n            }\n\n            NotificationConstants.MaxWidth = 1024;\n            notificationManager.Show( content, \"\", no.ExpTime );\n            NotificationConstants.MaxWidth = 350;\n\n            _ = User32.EnumWindows( ToastWindowFilter, 0 );\n        }\n\n        private static bool ToastWindowFilter( IntPtr hWnd, int lParam )\n        {\n            var sbTitle = new StringBuilder( 128 );\n            User32.GetWindowText( hWnd, sbTitle, sbTitle.Capacity );\n            var title = sbTitle.ToString();\n\n            var sbCName = new StringBuilder( 512 );\n            _ = User32.GetClassName( hWnd, sbCName, sbCName.Capacity );\n            var classname = sbCName.ToString();\n\n            if ( title == \"ToastWindow\" && classname.StartsWith( \"HwndWrapper[VirtualSpace\" ) )\n            {\n                var exStyle = User32.GetWindowLong( hWnd, (int)GetWindowLongFields.GWL_EXSTYLE );\n                exStyle |= User32.WS_EX_TOOLWINDOW;\n                User32.SetWindowLongPtr( new HandleRef( null, hWnd ), (int)GetWindowLongFields.GWL_EXSTYLE, exStyle );\n                return false;\n            }\n\n            return true;\n        }\n\n        private enum GetWindowLongFields\n        {\n            GWL_USERDATA   = -21, // 0xFFFFFFEB\n            GWL_EXSTYLE    = -20, // 0xFFFFFFEC\n            GWL_STYLE      = -16, // 0xFFFFFFF0\n            GWL_ID         = -12, // 0xFFFFFFF4\n            GWL_HWNDPARENT = -8, // 0xFFFFFFF8\n            GWL_HINSTANCE  = -6, // 0xFFFFFFFA\n            GWL_WNDPROC    = -4 // 0xFFFFFFFC\n        }\n\n        private static class User32\n        {\n            public delegate bool EnumWindowsProc( IntPtr hWnd, int lParam );\n\n            public const int WS_EX_TOOLWINDOW = 0x80;\n\n            [DllImport( \"user32.dll\", CharSet = CharSet.Auto )]\n            public static extern int GetWindowLong( IntPtr hWnd, int nIndex );\n\n            public static IntPtr SetWindowLongPtr( HandleRef hWnd, int nIndex, int dwNewLong )\n            {\n                if ( IntPtr.Size == 8 )\n                    return SetWindowLongPtr64( hWnd, nIndex, (IntPtr)dwNewLong );\n                else\n                    return new IntPtr( SetWindowLong32( hWnd, nIndex, dwNewLong ) );\n            }\n\n            [DllImport( \"user32.dll\", EntryPoint = \"SetWindowLong\" )]\n            private static extern int SetWindowLong32( HandleRef hWnd, int nIndex, int dwNewLong );\n\n            [DllImport( \"user32.dll\", EntryPoint = \"SetWindowLongPtr\" )]\n            private static extern IntPtr SetWindowLongPtr64( HandleRef hWnd, int nIndex, IntPtr dwNewLong );\n\n            [DllImport( \"user32.dll\" )]\n            public static extern int GetWindowText( IntPtr hWnd, StringBuilder buf, int nMaxCount );\n\n            [DllImport( \"user32.dll\", SetLastError = true, CharSet = CharSet.Auto )]\n            public static extern int GetClassName( IntPtr hWnd, StringBuilder lpClassName, int nMaxCount );\n\n            [DllImport( \"user32.dll\" )]\n            public static extern int EnumWindows( EnumWindowsProc func, int lParam );\n        }\n    }\n\n    public class NotifyObject\n    {\n        public string           Title      { get; set; } = \"\";\n        public string           Message    { get; set; } = \"\";\n        public NotificationType Type       { get; set; }\n        public SolidColorBrush? Background { get; set; }\n        public SolidColorBrush? Foreground { get; set; }\n        public TimeSpan         ExpTime    { get; set; } = TimeSpan.FromSeconds( 10 );\n    }\n}"
  },
  {
    "path": "Logger/Logger.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFrameworks>net6.0-windows</TargetFrameworks>\n        <LangVersion>9</LangVersion>\n        <Nullable>enable</Nullable>\n    </PropertyGroup>\n\n    <ItemGroup>\n        <PackageReference Include=\"Notification.Wpf\" Version=\"6.1.0.1\" />\n        <PackageReference Include=\"Serilog\" Version=\"2.10.0\" />\n        <PackageReference Include=\"Serilog.Sinks.File\" Version=\"5.0.0\" />\n    </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "Logger/Manager.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Configuration;\nusing System.IO;\nusing Serilog;\nusing Serilog.Core;\nusing Serilog.Events;\n\nnamespace VirtualSpace.AppLogs\n{\n    public static class LogManager\n    {\n        private static readonly LoggingLevelSwitch LevelSwitch = new( LogEventLevel.Verbose );\n\n        public const LogEventLevel LOG_LEVEL_EVENT = (LogEventLevel)0xFF;\n\n        public static Serilog.Core.Logger RootLogger;\n\n        private static string _logsFolder = \"Logs\";\n\n        public static string LogsPath\n        {\n            get\n            {\n                var appPath       = Environment.ProcessPath!;\n                var appRootFolder = Directory.GetParent( appPath )!.FullName;\n                return Path.Combine( appRootFolder, _logsFolder );\n            }\n        }\n\n        public static void InitLogger( string folder )\n        {\n            _logsFolder = folder;\n            folder     = LogsPath;\n            RootLogger = new LoggerConfiguration()\n                .MinimumLevel.ControlledBy( LevelSwitch )\n                .WriteTo.Logger( c =>\n                    c.Filter.ByIncludingOnly( evt => evt.Level == LogEventLevel.Verbose ).WriteTo.File( $\"{folder}/verbose.txt\", LogEventLevel.Verbose ) )\n                .WriteTo.Logger( c =>\n                    c.Filter.ByIncludingOnly( evt => evt.Level == LogEventLevel.Debug ).WriteTo.File( $\"{folder}/debug.txt\", LogEventLevel.Debug ) )\n                .WriteTo.Logger( c =>\n                    c.Filter.ByIncludingOnly( evt => evt.Level == LogEventLevel.Information ).WriteTo.File( $\"{folder}/info.txt\", LogEventLevel.Information ) )\n                .WriteTo.Logger( c =>\n                    c.Filter.ByIncludingOnly( evt => evt.Level == LogEventLevel.Warning ).WriteTo.File( $\"{folder}/warning.txt\", LogEventLevel.Warning ) )\n                .WriteTo.Logger( c =>\n                    c.Filter.ByIncludingOnly( evt => evt.Level == LogEventLevel.Error ).WriteTo.File( $\"{folder}/error.txt\", LogEventLevel.Error ) )\n                .WriteTo.Logger( c =>\n                    c.Filter.ByIncludingOnly( evt => evt.Level == LogEventLevel.Fatal ).WriteTo.File( $\"{folder}/fatal.txt\", LogEventLevel.Fatal ) )\n                .WriteTo.Logger( c =>\n                    c.Filter.ByIncludingOnly( evt => evt.Level == LOG_LEVEL_EVENT ).WriteTo.File( $\"{folder}/event.txt\", LOG_LEVEL_EVENT ) )\n                .CreateLogger();\n        }\n\n        public static void GorgeousDividingLine()\n        {\n            const string line = \"==================================================\";\n            RootLogger.Verbose( line );\n            RootLogger.Debug( line );\n            RootLogger.Information( line );\n            RootLogger.Warning( line );\n            RootLogger.Error( line );\n            RootLogger.Fatal( line );\n            RootLogger.Write( LOG_LEVEL_EVENT, line );\n        }\n\n        public static void SetLogLevel( string level )\n        {\n            LevelSwitch.MinimumLevel = level switch\n            {\n                \"DEBUG\" => LogEventLevel.Verbose,\n                \"EVENT\" => LogEventLevel.Debug,\n                \"INFO\" => LogEventLevel.Information,\n                \"WARNING\" => LogEventLevel.Warning,\n                \"ERROR\" => LogEventLevel.Error,\n                \"FATAL\" => LogEventLevel.Fatal,\n                _ => LogEventLevel.Information\n            };\n        }\n    }\n}"
  },
  {
    "path": "Plugin/Commons/Plugin.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFrameworks>net6.0-windows</TargetFrameworks>\n        <Nullable>enable</Nullable>\n        <LangVersion>9</LangVersion>\n    </PropertyGroup>\n\n</Project>\n"
  },
  {
    "path": "Plugin/Commons/PluginInfo.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Collections.Generic;\n\nnamespace VirtualSpace.Plugin\n{\n    public class PluginInfo\n    {\n        public string          Folder;\n        public IntPtr          Handle;\n        public int             ProcessId;\n        public PluginType      Type;\n        public string          Name            { get; set; }\n        public string          Display         { get; set; }\n        public string          Version         { get; set; }\n        public string          Author          { get; set; }\n        public string          Email           { get; set; }\n        public string          Entry           { get; set; }\n        public bool            AutoStart       { get; set; }\n        public AutoStartTiming AutoStartTiming { get; set; } = AutoStartTiming.MainWindowLoaded;\n        public Policy?         RestartPolicy   { get; set; }\n        public Policy?         ClosePolicy     { get; set; }\n        public Requirements?   Requirements    { get; set; }\n    }\n\n    public class Policy\n    {\n        public PolicyTrigger Trigger { get; set; }\n        public List<string>  Values  { get; set; }\n        public bool          Enabled { get; set; }\n    }\n\n    public enum PolicyTrigger\n    {\n        WINDOWS_MESSAGE\n    }\n\n    public enum PluginType\n    {\n        NONE,\n        VD_SWITCH_OBSERVER,\n        UPDATER\n    }\n\n    public class Requirements\n    {\n        public WinVer   WinVer      { get; set; }\n        public Version? HostVersion { get; set; }\n    }\n\n    public class WinVer\n    {\n        public Ver  Min { get; set; }\n        public Ver? Max { get; set; }\n    }\n\n    public class Ver\n    {\n        public int Major { get; set; }\n        public int Build { get; set; }\n    }\n\n    public enum AutoStartTiming\n    {\n        AppStart,\n        MainWindowLoaded\n    }\n}"
  },
  {
    "path": "Plugin/Commons/PluginManager.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Text.Json;\n\nnamespace VirtualSpace.Plugin\n{\n    public static class PluginManager\n    {\n        public const           string     PluginInfoFile = \"plugin.json\";\n        public static readonly PluginInfo PluginInfo     = GetPluginInfo();\n\n        private static PluginInfo GetPluginInfo()\n        {\n            var file = Path.Combine( GetAppFolder(), PluginInfoFile );\n            return LoadFromJson<PluginInfo>( file );\n        }\n\n        public static string GetAppPath()\n        {\n            return Process.GetCurrentProcess().MainModule.FileName;\n        }\n\n        public static string GetAppFolder()\n        {\n            return Directory.GetParent( GetAppPath() ).FullName;\n        }\n\n        public static T? LoadFromJson<T>( string infoFile )\n        {\n            using var fs     = new FileStream( infoFile, FileMode.Open, FileAccess.Read );\n            var       buffer = new byte[fs.Length];\n            _ = fs.Read( buffer, 0, (int)fs.Length );\n            var utf8Reader = new Utf8JsonReader( buffer );\n            return JsonSerializer.Deserialize<T>( ref utf8Reader );\n        }\n\n        public static bool CheckRequirements( Requirements? req )\n        {\n            var check   = false;\n            var version = Environment.OSVersion.Version;\n\n            if ( version.Major >= req?.WinVer.Min.Major && version.Build >= req.WinVer.Min.Build )\n                check = true;\n\n            if ( req?.WinVer.Max != null && ( version.Major > req.WinVer.Max.Major || version.Build > req.WinVer.Max.Build ) )\n                check = false;\n\n            return check;\n        }\n\n        public static void SavePluginInfo( PluginInfo pi )\n        {\n            var file     = Path.Combine( pi.Folder, PluginInfoFile );\n            var contents = JsonSerializer.SerializeToUtf8Bytes( pi, new JsonSerializerOptions {WriteIndented = true} );\n            File.WriteAllBytesAsync( file, contents );\n        }\n    }\n}"
  },
  {
    "path": "Plugin/Commons/WinApi.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Runtime.InteropServices;\n\nnamespace VirtualSpace.Plugin\n{\n    public static class WinApi\n    {\n        public const int WM_SYSCOMMAND    = 0x0112;\n        public const int SC_MAXIMIZE      = 0xF030;\n        public const int SC_MINIMIZE      = 0xF020;\n        public const int SC_RESTORE       = 0xF120;\n        public const int SC_SIZE          = 0xF000;\n        public const int SC_MOVE          = 0xF010;\n        public const int SC_CLOSE         = 0xF060;\n        public const int WM_HOTKEY        = 0x0312;\n        public const int WM_CLOSE         = 0x0010;\n        public const int WM_QUIT          = 0x0012;\n        public const int WM_DESTROY       = 0x0002;\n        public const int WM_MOUSEACTIVATE = 0x0021;\n        public const int MA_NOACTIVATE    = 0x3;\n        public const int WM_COPYDATA      = 0x004A;\n\n        private const int WM_USER           = 0x0400;\n        public const  int UM_SWITCHDESKTOP  = WM_USER + 1;\n        public const  int UM_PLUGINSETTINGS = WM_USER + 2;\n        public const  int UM_OTHERSCREENS   = WM_USER + 3;\n        public const  int UM_RESTART        = WM_USER + 4;\n\n        [DllImport( \"user32.dll\", CharSet = CharSet.Auto )]\n        public static extern bool PostMessage( IntPtr hWnd, int msg, uint wParam, uint lParam );\n    }\n}"
  },
  {
    "path": "Plugin/PluginHost/PluginConst.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nnamespace VirtualSpace.Plugin\n{\n    public static class PluginConst\n    {\n        public const string UxdDisplayChangeMessage          = \"UxdDisplayChangeMessage\";\n        public const string HotPlugDetected                  = \"HotplugDetected\";\n        public const string DirectInputNotificationMsgString = \"DIRECTINPUT_NOTIFICATION_MSGSTRING\";\n        public const int    RestartDelay                     = 5000;\n    }\n}"
  },
  {
    "path": "Plugin/PluginHost/PluginHost.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing System.Threading.Tasks;\nusing VirtualSpace.AppLogs;\n\nnamespace VirtualSpace.Plugin\n{\n    public static class PluginHost\n    {\n        public static readonly List<PluginInfo> Plugins = new();\n\n        public static readonly Dictionary<string, uint> CareAboutMessages = new()\n        {\n            {PluginConst.DirectInputNotificationMsgString, 0},\n            {PluginConst.HotPlugDetected, 0}\n        };\n\n        /// <summary>\n        /// 此处注册的是插件的静态信息；\n        /// 插件的运行时信息，则在插件启动后通过 IPC 自行报道给宿主\n        /// </summary>\n        /// <param name=\"pluginsPath\"></param>\n        public static void RegisterPlugins( string pluginsPath )\n        {\n            var pluginFolders = Directory.GetDirectories( pluginsPath );\n            foreach ( var path in pluginFolders )\n            {\n                var infoFile = Path.Combine( path, PluginManager.PluginInfoFile );\n                if ( !File.Exists( infoFile ) )\n                {\n                    Logger.Warning( $\"[PLUGIN] missing {PluginManager.PluginInfoFile} in {path}\" );\n                    continue;\n                }\n\n                var pluginInfo = PluginManager.LoadFromJson<PluginInfo>( infoFile );\n                if ( pluginInfo == null )\n                {\n                    Logger.Warning( $\"[PLUGIN] invalid {PluginManager.PluginInfoFile}\" );\n                    continue;\n                }\n\n                var alreadyLoaded = Plugins.Find( p => p.Name == pluginInfo.Name );\n                if ( alreadyLoaded != null ) continue;\n\n                if ( pluginInfo.Requirements is null )\n                {\n                    Logger.Warning( $\"[PLUGIN] {pluginInfo.Display} has no 'Requirements' info\" );\n                    continue;\n                }\n\n                if ( pluginInfo.Requirements.HostVersion == null ||\n                     pluginInfo.Requirements.HostVersion > GetHostVersion() )\n                {\n                    Logger.Warning( $\"[PLUGIN] {pluginInfo.Display} not satisfy the host version\" );\n                    continue;\n                }\n\n                pluginInfo.Folder = path;\n\n                Plugins.Add( pluginInfo );\n                Logger.Info( $\"[PLUGIN] {pluginInfo.Display} Registered.\" );\n\n                if ( pluginInfo is {AutoStart: true, AutoStartTiming: AutoStartTiming.AppStart} )\n                    StartPlugin( pluginInfo );\n            }\n        }\n\n        public static void AutoStartAfterMainWindowLoaded()\n        {\n            foreach ( var pi in Plugins.Where( pi => pi is {AutoStart: true, AutoStartTiming: AutoStartTiming.MainWindowLoaded} ) )\n            {\n                StartPlugin( pi );\n            }\n        }\n\n        private static void StartExe( string exe )\n        {\n            Task.Run( () => Process.Start( exe ) );\n        }\n\n        public static void PluginSettings( PluginInfo pluginInfo )\n        {\n            WinApi.PostMessage( pluginInfo.Handle, WinApi.UM_PLUGINSETTINGS, 0, 0 );\n        }\n\n        public static void StartPlugin( PluginInfo pluginInfo )\n        {\n            if ( !PluginManager.CheckRequirements( pluginInfo.Requirements ) ) return;\n            Logger.Info( $\"[PLUGIN.Start] {pluginInfo.Display}\" );\n            StartExe( Path.Combine( pluginInfo.Folder, pluginInfo.Entry ) );\n        }\n\n        public static void ClosePlugin( PluginInfo pluginInfo )\n        {\n            if ( !string.IsNullOrEmpty( pluginInfo.Display ) )\n                Logger.Info( $\"[PLUGIN.Close] {pluginInfo.Display}\" );\n            WinApi.PostMessage( pluginInfo.Handle, WinApi.WM_CLOSE, 0, 0 );\n            // WinApi.PostMessage( pluginInfo.Handle, WinApi.WM_QUIT, 0, 0 );\n            // WinApi.PostMessage( pluginInfo.Handle, WinApi.WM_DESTROY, 0, 0 );\n        }\n\n        public static void RestartPlugin( PluginInfo pluginInfo )\n        {\n            try\n            {\n                WinApi.PostMessage( pluginInfo.Handle, WinApi.UM_RESTART, 0, PluginConst.RestartDelay );\n                Logger.Info( $\"[PLUGIN] {pluginInfo.Display} Restarted.\" );\n            }\n            catch ( Exception ex )\n            {\n                Logger.Warning( \"Failed Restart Plugin, Abort Operation.\" );\n                Logger.Warning( ex.Message );\n            }\n        }\n\n        private static Version GetHostVersion()\n        {\n            var fileVersion = ( (AssemblyFileVersionAttribute)Attribute.GetCustomAttribute(\n                Assembly.GetEntryAssembly(),\n                typeof( AssemblyFileVersionAttribute ),\n                false ) ).Version;\n            return new Version( fileVersion );\n        }\n    }\n}"
  },
  {
    "path": "Plugin/PluginHost/PluginHost.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFrameworks>net6.0-windows</TargetFrameworks>\n        <Nullable>enable</Nullable>\n        <LangVersion>9</LangVersion>\n    </PropertyGroup>\n\n    <ItemGroup>\n      <ProjectReference Include=\"..\\..\\Logger\\Logger.csproj\" />\n      <ProjectReference Include=\"..\\Commons\\Plugin.csproj\" />\n    </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "Plugins.sln/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore\n\n# User-specific files\n*.rsuser\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Mono auto generated files\nmono_crash.*\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\n[Ww][Ii][Nn]32/\n[Aa][Rr][Mm]/\n[Aa][Rr][Mm]64/\nbld/\n[Bb]in/\n[Oo]bj/\n[Ll]og/\n[Ll]ogs/\n\n# Visual Studio 2015/2017 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# Visual Studio 2017 auto generated files\nGenerated\\ Files/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUnit\n*.VisualState.xml\nTestResult.xml\nnunit-*.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# Benchmark Results\nBenchmarkDotNet.Artifacts/\n\n# .NET Core\nproject.lock.json\nproject.fragment.lock.json\nartifacts/\n\n# Tye\n.tye/\n\n# ASP.NET Scaffolding\nScaffoldingReadMe.txt\n\n# StyleCop\nStyleCopReport.xml\n\n# Files built by Visual Studio\n*_i.c\n*_p.c\n*_h.h\n*.ilk\n*.meta\n*.obj\n*.iobj\n*.pch\n*.pdb\n*.ipdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*_wpftmp.csproj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n*.VC.db\n*.VC.VC.opendb\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# Visual Studio Trace Files\n*.e2e\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# AxoCover is a Code Coverage Tool\n.axoCover/*\n!.axoCover/settings.json\n\n# Coverlet is a free, cross platform Code Coverage Tool\ncoverage*.json\ncoverage*.xml\ncoverage*.info\n\n# Visual Studio code coverage results\n*.coverage\n*.coveragexml\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# Note: Comment the next line if you want to checkin your web deploy settings,\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# Microsoft Azure Web App publish settings. Comment the next line if you want to\n# checkin your Azure Web App publish settings, but sensitive information contained\n# in these scripts will be unencrypted\nPublishScripts/\n\n# NuGet Packages\n*.nupkg\n# NuGet Symbol Packages\n*.snupkg\n# The packages folder can be ignored because of Package Restore\n**/[Pp]ackages/*\n# except build/, which is used as an MSBuild target.\n!**/[Pp]ackages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/[Pp]ackages/repositories.config\n# NuGet v3's project.json files produces more ignorable files\n*.nuget.props\n*.nuget.targets\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Windows Store app package directories and files\nAppPackages/\nBundleArtifacts/\nPackage.StoreAssociation.xml\n_pkginfo.txt\n*.appx\n*.appxbundle\n*.appxupload\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!?*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.jfm\n*.pfx\n*.publishsettings\norleans.codegen.cs\n\n# Including strong name files can present a security risk\n# (https://github.com/github/gitignore/pull/2483#issue-259490424)\n#*.snk\n\n# Since there are multiple workflows, uncomment next line to ignore bower_components\n# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)\n#bower_components/\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\nServiceFabricBackup/\n*.rptproj.bak\n\n# SQL Server files\n*.mdf\n*.ldf\n*.ndf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n*.rptproj.rsuser\n*- [Bb]ackup.rdl\n*- [Bb]ackup ([0-9]).rdl\n*- [Bb]ackup ([0-9][0-9]).rdl\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\nnode_modules/\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)\n*.vbw\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\npaket-files/\n\n# FAKE - F# Make\n.fake/\n\n# CodeRush personal settings\n.cr/personal\n\n# Python Tools for Visual Studio (PTVS)\n__pycache__/\n*.pyc\n\n# Cake - Uncomment if you are using it\n# tools/**\n# !tools/packages.config\n\n# Tabs Studio\n*.tss\n\n# Telerik's JustMock configuration file\n*.jmconfig\n\n# BizTalk build output\n*.btp.cs\n*.btm.cs\n*.odx.cs\n*.xsd.cs\n\n# OpenCover UI analysis results\nOpenCover/\n\n# Azure Stream Analytics local run output\nASALocalRun/\n\n# MSBuild Binary and Structured Log\n*.binlog\n\n# NVidia Nsight GPU debugger configuration file\n*.nvuser\n\n# MFractors (Xamarin productivity tool) working folder\n.mfractor/\n\n# Local History for Visual Studio\n.localhistory/\n\n# BeatPulse healthcheck temp database\nhealthchecksdb\n\n# Backup folder for Package Reference Convert tool in Visual Studio 2017\nMigrationBackup/\n\n# Ionide (cross platform F# VS Code tools) working folder\n.ionide/\n\n# Fody - auto-generated XML schema\nFodyWeavers.xsd\n\n##\n## Visual studio for Mac\n##\n\n\n# globs\nMakefile.in\n*.userprefs\n*.usertasks\nconfig.make\nconfig.status\naclocal.m4\ninstall-sh\nautom4te.cache/\n*.tar.gz\ntarballs/\ntest-results/\n\n# Mac bundle stuff\n*.dmg\n*.app\n\n# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore\n# General\n.DS_Store\n.AppleDouble\n.LSOverride\n\n# Icon must end with two \\r\nIcon\n\n\n# Thumbnails\n._*\n\n# Files that might appear in the root of a volume\n.DocumentRevisions-V100\n.fseventsd\n.Spotlight-V100\n.TemporaryItems\n.Trashes\n.VolumeIcon.icns\n.com.apple.timemachine.donotpresent\n\n# Directories potentially created on remote AFP share\n.AppleDB\n.AppleDesktop\nNetwork Trash Folder\nTemporary Items\n.apdisk\n\n# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore\n# Windows thumbnail cache files\nThumbs.db\nehthumbs.db\nehthumbs_vista.db\n\n# Dump file\n*.stackdump\n\n# Folder config file\n[Dd]esktop.ini\n\n# Recycle Bin used on file shares\n$RECYCLE.BIN/\n\n# Windows Installer files\n*.cab\n*.msi\n*.msix\n*.msm\n*.msp\n\n# Windows shortcuts\n*.lnk\n\n# JetBrains Rider\n.idea/\n*.sln.iml\n\n##\n## Visual Studio Code\n##\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n!.vscode/extensions.json\n"
  },
  {
    "path": "Plugins.sln/COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "Plugins.sln/Cube3D/App.xaml",
    "content": "﻿<Application x:Class=\"Cube3D.App\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n             xmlns:interop=\"clr-namespace:System.Windows.Interop;assembly=PresentationCore\"\n             StartupUri=\"MainWindow.xaml\">\n\n    <Application.Resources>\n        <ResourceDictionary>\n            <interop:D3DImage x:Key=\"Front\" />\n            <interop:D3DImage x:Key=\"Others\" />\n            <LinearGradientBrush x:Key=\"BackgroundLgb\" StartPoint='0.5,0' EndPoint='0.5,1'>\n                <GradientStop Color='Black' Offset='0' />\n                <GradientStop Color='#FF323334' Offset='1' />\n            </LinearGradientBrush>\n            <Brush x:Key=\"BackgroundTrans\">\n                Transparent\n            </Brush>\n        </ResourceDictionary>\n    </Application.Resources>\n\n</Application>"
  },
  {
    "path": "Plugins.sln/Cube3D/App.xaml.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of Cube3D.\n\nCube3D is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nCube3D is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with Cube3D. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System.Diagnostics;\nusing System.Windows;\nusing VirtualSpace.Plugin;\n\nnamespace Cube3D\n{\n    /// <summary>\n    ///     Interaction logic for App.xaml\n    /// </summary>\n    public partial class App : Application\n    {\n        protected override void OnStartup( StartupEventArgs e )\n        {\n            base.OnStartup( e );\n            var pluginInfo = PluginManager.PluginInfo;\n            if ( pluginInfo == null || string.IsNullOrEmpty( pluginInfo.Name ) )\n            {\n                MessageBox.Show( $\"{PluginManager.PluginInfoFile} invalid.\" );\n                Current.Shutdown();\n            }\n\n            if ( !PluginManager.CheckRequirements( pluginInfo.Requirements ) )\n            {\n                MessageBox.Show( \"Plugin Error.\\nThe system does not meet the Requirements.\" );\n                Current.Shutdown();\n            }\n        }\n\n        public static void Restart()\n        {\n            Process.Start( PluginManager.GetAppPath() );\n            Current.Shutdown();\n        }\n    }\n}"
  },
  {
    "path": "Plugins.sln/Cube3D/AssemblyInfo.cs",
    "content": "using System.Windows;\n\n[assembly: ThemeInfo(\n    ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located\n    //(used if a resource is not found in the page,\n    // or application resource dictionaries)\n    ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located\n    //(used if a resource is not found in the page,\n    // app, or any theme specific resource dictionaries)\n)]"
  },
  {
    "path": "Plugins.sln/Cube3D/AutoVersion.tt",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of Cube3D.\n\nCube3D is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nCube3D is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with Cube3D. If not, see <https://www.gnu.org/licenses/>.\n*/\n\n<#@ template debug=\"false\" hostspecific=\"false\" language=\"C#\" #>\n<#@ output extension=\".cs\" #>\n\n<#@ Assembly Name=\"System.Core.dll\" #>\n<#@ Assembly Name=\"System.Windows.Forms.dll\" #>\n<#@ import namespace=\"System.IO\" #>\n\nusing System.Reflection;\n\n[assembly: AssemblyProduct(\"<#= AppName #>\")]\n\n[assembly: AssemblyTitle(\"<#= AppDesc #>\")]\n[assembly: AssemblyDescription(\"<#= AppDesc #>\")]\n\n[assembly: AssemblyCompany(\"https://github.com/newlooper\")]\n\n[assembly: AssemblyCopyright(\"Copyright © <#= Copyright #>\")]\n\n[assembly: AssemblyVersion(\"<#= MAJOR #>.<#= MINOR #>.<#= DaysSinceProjectStarted #>.<#= MinutesSinceMidnight #>\")]\n[assembly: AssemblyFileVersion(\"<#= MAJOR #>.<#= MINOR #>.<#= DaysSinceProjectStarted #>.<#= MinutesSinceMidnight #>\")]\n\n<#+\n    private static readonly DateTime ProjectStartedDate = new( 2022, 2, 28 );\n\n    private static readonly string Copyright = ProjectStartedDate.Year + \" - \" + DateTime.Now.Year;\n    private static readonly string AppName = new DirectoryInfo( \".\" ).Name;\n    private static readonly string AppDesc = \"VirtualSpace.Plugin - Cube3D\";\n\n        private const int MAJOR = 1;\n        private const int MINOR = 0;\n\n    private static readonly int DaysSinceProjectStarted = (int)( DateTime.UtcNow - ProjectStartedDate ).TotalDays;\n    private static readonly int MinutesSinceMidnight = (int)DateTime.UtcNow.TimeOfDay.TotalMinutes;\n#>"
  },
  {
    "path": "Plugins.sln/Cube3D/COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "Plugins.sln/Cube3D/Config/Const.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of Cube3D.\n// \n// Cube3D is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// Cube3D is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with Cube3D. If not, see <https://www.gnu.org/licenses/>.\n\nnamespace Cube3D.Config\n{\n    public static class Const\n    {\n        public const double FakeHideX                 = -10000.0;\n        public const double FakeHideY                 = -10000.0;\n        public const int    AnimationDurationMin      = 100;\n        public const int    AnimationDurationMax      = 1000;\n        public const int    CheckAliveIntervalMin     = 1;\n        public const int    CheckAliveIntervalMax     = 60;\n        public const int    CheckAliveIntervalDefault = 10;\n        public const string Front                     = nameof( Front );\n        public const string Others                    = nameof( Others );\n    }\n}"
  },
  {
    "path": "Plugins.sln/Cube3D/Config/Settings.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of Cube3D.\n// \n// Cube3D is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// Cube3D is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with Cube3D. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing Cube3D.Effects;\n\nnamespace Cube3D.Config\n{\n    public class Settings\n    {\n        private int _animationDuration;\n        private int _checkAliveInterval;\n\n        public int AnimationDuration\n        {\n            get => _animationDuration;\n            set\n            {\n                if ( value < Const.AnimationDurationMin || value > Const.AnimationDurationMax )\n                {\n                    _animationDuration = Const.AnimationDurationMin;\n                }\n                else\n                {\n                    _animationDuration = value;\n                }\n            }\n        }\n\n        public int CheckAliveInterval\n        {\n            get => _checkAliveInterval;\n            set\n            {\n                if ( value < Const.CheckAliveIntervalMin || value > Const.CheckAliveIntervalMax )\n                {\n                    _checkAliveInterval = Const.CheckAliveIntervalDefault;\n                }\n                else\n                {\n                    _checkAliveInterval = value;\n                }\n            }\n        }\n\n        public EffectType     SelectedEffect                   { get; set; }\n        public EaseType       EaseType                         { get; set; } = EaseType.None;\n        public EaseMode       EaseMode                         { get; set; } = EaseMode.EaseOut;\n        public TransitionType TransitionType                   { get; set; } = TransitionType.AnimationAndNotificationGrid;\n        public bool           ShowNotificationGridOnAllScreens { get; set; }\n    }\n\n    [Flags]\n    public enum TransitionType\n    {\n        AnimationOnly                = 0b0001,\n        NotificationGridOnly         = 0b0010,\n        AnimationAndNotificationGrid = AnimationOnly | NotificationGridOnly\n    }\n}"
  },
  {
    "path": "Plugins.sln/Cube3D/Config/SettingsManager.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of Plugins.\n// \n// Plugins is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// Plugins is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with Plugins. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.IO;\nusing System.Text.Json;\nusing VirtualSpace.Plugin;\n\nnamespace Cube3D.Config\n{\n    public class SettingsManager\n    {\n        private const          string   PluginSettingFile = \"settings.json\";\n        public static readonly Settings Settings          = GetSettings();\n\n        private static Settings GetSettings()\n        {\n            var file = Path.Combine( PluginManager.GetAppFolder(), PluginSettingFile );\n            return PluginManager.LoadFromJson<Settings>( file );\n        }\n\n        public static void SaveJson( string file = null )\n        {\n            file ??= Path.Combine( PluginManager.GetAppFolder(), PluginSettingFile );\n            var contents = JsonSerializer.SerializeToUtf8Bytes( Settings, new JsonSerializerOptions {WriteIndented = true} );\n            File.WriteAllBytesAsync( file, contents );\n        }\n    }\n}"
  },
  {
    "path": "Plugins.sln/Cube3D/Cube3D.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk.WindowsDesktop\">\n\n    <PropertyGroup>\n        <OutputType>WinExe</OutputType>\n        <TargetFrameworks>net6.0-windows10.0.20348.0;net6.0-windows10.0.22000.0;</TargetFrameworks>\n        <LangVersion>9</LangVersion>\n        <UseWPF>true</UseWPF>\n        <CsWinRTEnabled>false</CsWinRTEnabled>\n        <ApplicationManifest>app.manifest</ApplicationManifest>\n    </PropertyGroup>\n\n    <PropertyGroup>\n        <GenerateAssemblyInfo>false</GenerateAssemblyInfo>\n        <OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles>\n    </PropertyGroup>\n\n    <Target Name=\"TextTemplateTransform\" BeforeTargets=\"BeforeBuild\" Condition=\"'$(Configuration)'=='Release'\">\n        <Message Text=\"======TextTemplateTransform begin======\" Importance=\"High\" />\n        <Exec WorkingDirectory=\"$(ProjectDir)\"\n              Command=\"&quot;$(DevEnvDir)TextTransform.exe&quot; -out &quot;$(ProjectDir)AutoVersion.cs&quot; &quot;$(ProjectDir)AutoVersion.tt&quot;\">\n            <Output TaskParameter=\"ConsoleOutput\" PropertyName=\"OutputOfExec\" />\n        </Exec>\n        <Message Text=\"======TextTemplateTransform end======\" Importance=\"High\" />\n    </Target>\n\n    <ItemGroup>\n        <Compile Update=\"AutoVersion.cs\">\n            <DesignTime>True</DesignTime>\n            <DependentUpon>AutoVersion.tt</DependentUpon>\n        </Compile>\n    </ItemGroup>\n\n    <ItemGroup>\n        <Compile Remove=\"Properties\\**\" />\n        <EmbeddedResource Remove=\"Properties\\**\" />\n        <None Remove=\"Properties\\**\" />\n        <Page Remove=\"Properties\\**\" />\n        <None Update=\"settings.json\">\n            <CopyToOutputDirectory>Always</CopyToOutputDirectory>\n        </None>\n        <None Update=\"plugin.json\">\n            <CopyToOutputDirectory>Always</CopyToOutputDirectory>\n        </None>\n    </ItemGroup>\n\n    <ItemGroup>\n        <ProjectReference Include=\"..\\..\\Ipc\\IpcClient\\IpcClient.csproj\" />\n        <ProjectReference Include=\"..\\..\\Plugin\\Commons\\Plugin.csproj\" />\n        <ProjectReference Include=\"..\\ScreenCapture\\ScreenCapture.csproj\" />\n    </ItemGroup>\n\n    <ItemGroup>\n        <Folder Include=\"Helpers\\\" />\n    </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "Plugins.sln/Cube3D/D3DImages/D3DImages.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of Cube3D.\n// \n// Cube3D is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// Cube3D is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with Cube3D. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.Collections.Generic;\nusing System.Windows;\nusing System.Windows.Interop;\nusing Cube3D.Config;\n\nnamespace Cube3D.D3DImages\n{\n    public static class D3DImages\n    {\n        public static readonly D3DImage FrontD3DImage  = Application.Current.Resources[Const.Front] as D3DImage;\n        public static readonly D3DImage OthersD3DImage = Application.Current.Resources[Const.Others] as D3DImage;\n\n        public static readonly Dictionary<string, D3DImageInfo> D3DImageDict = new()\n        {\n            {\n                Const.Front, new D3DImageInfo\n                {\n                    Image = FrontD3DImage\n                }\n            },\n            {\n                Const.Others, new D3DImageInfo\n                {\n                    Image = OthersD3DImage\n                }\n            }\n        };\n    }\n}"
  },
  {
    "path": "Plugins.sln/Cube3D/Effects/Cube.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of Cube3D.\n// \n// Cube3D is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// Cube3D is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with Cube3D. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Windows;\nusing System.Windows.Media;\nusing System.Windows.Media.Animation;\nusing System.Windows.Media.Media3D;\nusing Cube3D.Config;\n\nnamespace Cube3D.Effects\n{\n    public class Cube : Effect\n    {\n        private static readonly Dictionary<KeyCode, RotateTransform3D> TransformDirections = new()\n        {\n            {\n                KeyCode.Left, new RotateTransform3D( new AxisAngleRotation3D( new Vector3D( 0, 1, 0 ), 0 ) )\n                {\n                    CenterX = MeshWidth / 2,\n                    CenterZ = -MeshWidth / 2\n                }\n            },\n            {\n                KeyCode.Right, new RotateTransform3D( new AxisAngleRotation3D( new Vector3D( 0, -1, 0 ), 0 ) )\n                {\n                    CenterX = MeshWidth / 2,\n                    CenterZ = -MeshWidth / 2\n                }\n            },\n            {\n                KeyCode.Up, new RotateTransform3D( new AxisAngleRotation3D( new Vector3D( 1, 0, 0 ), 0 ) )\n                {\n                    CenterY = MeshHeight / 2,\n                    CenterZ = -MeshHeight / 2\n                }\n            },\n            {\n                KeyCode.Down, new RotateTransform3D( new AxisAngleRotation3D( new Vector3D( -1, 0, 0 ), 0 ) )\n                {\n                    CenterY = MeshHeight / 2,\n                    CenterZ = -MeshHeight / 2\n                }\n            }\n        };\n\n        /////////////////////////////\n        // 立方体\n        // 前/后表面 —— 水平/垂直旋转\n        // 左/右表面 —— 水平旋转\n        // 上/下表面 —— 垂直旋转\n        private readonly Model3DGroup    _cube           = new();\n        private readonly GeometryModel3D _cubeBack       = new();\n        private readonly MeshGeometry3D  _cubeBackMesh   = new();\n        private readonly GeometryModel3D _cubeBottom     = new();\n        private readonly MeshGeometry3D  _cubeBottomMesh = new();\n        private readonly GeometryModel3D _cubeFront      = new();\n        private readonly MeshGeometry3D  _cubeFrontMesh  = new();\n        private readonly GeometryModel3D _cubeLeft       = new();\n        private readonly MeshGeometry3D  _cubeLeftMesh   = new();\n        private readonly GeometryModel3D _cubeRight      = new();\n        private readonly MeshGeometry3D  _cubeRightMesh  = new();\n        private readonly GeometryModel3D _cubeTop        = new();\n        private readonly MeshGeometry3D  _cubeTopMesh    = new();\n\n        public Cube()\n        {\n            Animation = new DoubleAnimation\n            {\n                From = 0,\n                To = 90,\n                FillBehavior = FillBehavior.Stop\n            };\n        }\n\n        public override void Build( Model3DGroup model3DGroup )\n        {\n            ////////////////////////////////////////////////////////////////\n            // front\n            _cubeFrontMesh.Positions.Add( new Point3D( 0, 0, 0 ) );\n            _cubeFrontMesh.Positions.Add( new Point3D( MeshWidth, 0, 0 ) );\n            _cubeFrontMesh.Positions.Add( new Point3D( MeshWidth, MeshHeight, 0 ) );\n            _cubeFrontMesh.Positions.Add( new Point3D( 0, MeshHeight, 0 ) );\n            AddTriangleIndices( _cubeFrontMesh );\n            AddTextureCoordinatesFront( _cubeFrontMesh );\n\n            ////////////////////////////////////////////////////////////////\n            // back\n            // _cubeBackMesh.Positions.Add( new Point3D( MeshWidth, 0, -MeshWidth ) );\n            // _cubeBackMesh.Positions.Add( new Point3D( 0, 0, -MeshWidth ) );\n            // _cubeBackMesh.Positions.Add( new Point3D( 0, MeshHeight, -MeshWidth ) );\n            // _cubeBackMesh.Positions.Add( new Point3D( MeshWidth, MeshHeight, -MeshWidth ) );\n            // AddTriangleIndices( _cubeBackMesh );\n            // AddTextureCoordinatesFront( _cubeBackMesh );\n\n            //////////////////////////////////////////////////////////////////////////////////////////////////////////\n            // CubeH\n\n            ////////////////////////////////////////////////////////////////\n            // left\n            _cubeLeftMesh.Positions.Add( new Point3D( 0, 0, -MeshWidth ) );\n            _cubeLeftMesh.Positions.Add( new Point3D( 0, 0, 0 ) );\n            _cubeLeftMesh.Positions.Add( new Point3D( 0, MeshHeight, 0 ) );\n            _cubeLeftMesh.Positions.Add( new Point3D( 0, MeshHeight, -MeshWidth ) );\n            AddTriangleIndices( _cubeLeftMesh );\n            AddTextureCoordinatesFront( _cubeLeftMesh );\n\n            ////////////////////////////////////////////////////////////////\n            // right\n            _cubeRightMesh.Positions.Add( new Point3D( MeshWidth, 0, 0 ) );\n            _cubeRightMesh.Positions.Add( new Point3D( MeshWidth, 0, -MeshWidth ) );\n            _cubeRightMesh.Positions.Add( new Point3D( MeshWidth, MeshHeight, -MeshWidth ) );\n            _cubeRightMesh.Positions.Add( new Point3D( MeshWidth, MeshHeight, 0 ) );\n            AddTriangleIndices( _cubeRightMesh );\n            AddTextureCoordinatesFront( _cubeRightMesh );\n\n            //////////////////////////////////////////////////////////////////////////////////////////////////////////\n            // CubeV\n\n            ////////////////////////////////////////////////////////////////\n            // top\n            _cubeTopMesh.Positions.Add( new Point3D( 0 * MeshWidth, 1 * MeshHeight, 0 ) );\n            _cubeTopMesh.Positions.Add( new Point3D( 1 * MeshWidth, 1 * MeshHeight, 0 ) );\n            _cubeTopMesh.Positions.Add( new Point3D( 1 * MeshWidth, 1 * MeshHeight, -MeshHeight ) );\n            _cubeTopMesh.Positions.Add( new Point3D( 0 * MeshWidth, 1 * MeshHeight, -MeshHeight ) );\n            AddTriangleIndices( _cubeTopMesh );\n            AddTextureCoordinatesFront( _cubeTopMesh );\n\n            ////////////////////////////////////////////////////////////////\n            // bottom\n            _cubeBottomMesh.Positions.Add( new Point3D( 0 * MeshWidth, 0 * MeshHeight, -MeshHeight ) );\n            _cubeBottomMesh.Positions.Add( new Point3D( 1 * MeshWidth, 0 * MeshHeight, -MeshHeight ) );\n            _cubeBottomMesh.Positions.Add( new Point3D( 1 * MeshWidth, 0 * MeshHeight, 0 ) );\n            _cubeBottomMesh.Positions.Add( new Point3D( 0 * MeshWidth, 0 * MeshHeight, 0 ) );\n            AddTriangleIndices( _cubeBottomMesh );\n            AddTextureCoordinatesFront( _cubeBottomMesh );\n\n            ////////////////////////////////////////////////////////////////\n            // Front 永远显示当前桌面；其在动画中定格，动画结束后归位并继续截屏\n            var frontMaterial = new DiffuseMaterial( new ImageBrush( D3DImages.D3DImages.FrontD3DImage ) );\n            _cubeFront.Material = frontMaterial;\n\n            ////////////////////////////////////////////////////////////////\n            // 其他位面永远显示目标桌面，可以共享同一个材质；其在动画中持续截屏，动画结束后归位并停止截屏\n            var othersMaterial = new DiffuseMaterial( new ImageBrush( D3DImages.D3DImages.OthersD3DImage ) );\n            // _cubeBack.Material = othersMaterial;\n            _cubeLeft.Material = othersMaterial;\n            _cubeRight.Material = othersMaterial;\n            _cubeTop.Material = othersMaterial;\n            _cubeBottom.Material = othersMaterial;\n\n            // _cubeFront.BackMaterial = frontMaterial;\n            // _cubeRight.BackMaterial = rightMaterial;\n            // _cubeBack.BackMaterial = backMaterial;\n            // _cubeLeft.BackMaterial = leftMaterial;\n            // _cubeTop.BackMaterial = topMaterial;\n            // _cubeBottom.BackMaterial = bottomMaterial;\n\n            ////////////////////////////////////////////\n            // set GeometryModel3D' mesh\n            _cubeFront.Geometry = _cubeFrontMesh;\n            // _cubeBack.Geometry = _cubeBackMesh;\n            _cubeLeft.Geometry = _cubeLeftMesh;\n            _cubeRight.Geometry = _cubeRightMesh;\n            _cubeTop.Geometry = _cubeTopMesh;\n            _cubeBottom.Geometry = _cubeBottomMesh;\n\n            ////////////////////////////////////////////\n            // Model3D/Model3DGroup\n            _cube.Children.Add( _cubeFront );\n            // _cube.Children.Add( _cubeBack );\n            _cube.Children.Add( _cubeLeft );\n            _cube.Children.Add( _cubeRight );\n            _cube.Children.Add( _cubeTop );\n            _cube.Children.Add( _cubeBottom );\n\n            model3DGroup.Children.Clear();\n            model3DGroup.Children.Add( _cube );\n            model3DGroup.Children.Add( CommonLight );\n        }\n\n        public override void AnimationInDirection( KeyCode dir, Model3DGroup model3DGroup, IEasingFunction ef = null )\n        {\n            switch ( dir )\n            {\n                case KeyCode.Left:\n                    Transform3D = TransformDirections[KeyCode.Left];\n                    break;\n                case KeyCode.Right:\n                    Transform3D = TransformDirections[KeyCode.Right];\n                    break;\n                case KeyCode.Up:\n                    Transform3D = TransformDirections[KeyCode.Up];\n                    break;\n                case KeyCode.Down:\n                    Transform3D = TransformDirections[KeyCode.Down];\n                    break;\n            }\n\n            if ( TransGroup.Children.Count == 0 )\n            {\n                TransGroup.Children.Add( Transform3D );\n            }\n            else\n            {\n                TransGroup.Children[0] = Transform3D;\n            }\n\n            model3DGroup.Transform = TransGroup;\n\n            var animation = (DoubleAnimation)Animation;\n            animation.Duration = new Duration( TimeSpan.FromMilliseconds( SettingsManager.Settings.AnimationDuration ) );\n            animation.EasingFunction = ef;\n            var transform = (RotateTransform3D)Transform3D;\n            transform.Rotation.BeginAnimation( AxisAngleRotation3D.AngleProperty, animation );\n        }\n    }\n}"
  },
  {
    "path": "Plugins.sln/Cube3D/Effects/Effect.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of Cube3D.\n// \n// Cube3D is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// Cube3D is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with Cube3D. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Windows;\nusing System.Windows.Media;\nusing System.Windows.Media.Animation;\nusing System.Windows.Media.Media3D;\n\nnamespace Cube3D.Effects\n{\n    public abstract class Effect\n    {\n        protected static readonly double           MeshHeight  = SystemParameters.PrimaryScreenHeight / SystemParameters.PrimaryScreenWidth;\n        protected static readonly double           MeshWidth   = 1.0;\n        protected static readonly AmbientLight     CommonLight = new() {Color = Colors.White};\n        protected readonly        Transform3DGroup TransGroup  = new();\n        protected                 Timeline         Animation;\n        protected                 Transform3D      Transform3D;\n\n        protected static void AddTriangleIndices( MeshGeometry3D meshGeometry3D )\n        {\n            meshGeometry3D.TriangleIndices.Add( 0 );\n            meshGeometry3D.TriangleIndices.Add( 1 );\n            meshGeometry3D.TriangleIndices.Add( 2 );\n            meshGeometry3D.TriangleIndices.Add( 2 );\n            meshGeometry3D.TriangleIndices.Add( 3 );\n            meshGeometry3D.TriangleIndices.Add( 0 );\n        }\n\n        protected static void AddTextureCoordinatesFront( MeshGeometry3D meshGeometry3D )\n        {\n            meshGeometry3D.TextureCoordinates.Add( new Point( 0, 1 ) );\n            meshGeometry3D.TextureCoordinates.Add( new Point( 1, 1 ) );\n            meshGeometry3D.TextureCoordinates.Add( new Point( 1, 0 ) );\n            meshGeometry3D.TextureCoordinates.Add( new Point( 0, 0 ) );\n        }\n\n        public abstract void Build( Model3DGroup model3DGroup );\n\n        public abstract void AnimationInDirection( KeyCode dir, Model3DGroup model3DGroup, IEasingFunction ef = null );\n\n        public void AddAnimationCompletedListener( EventHandler handler )\n        {\n            Animation.Completed += handler;\n        }\n    }\n\n    public enum EffectType\n    {\n        Cube,\n        InsideCube,\n        Slide,\n        Reveal,\n        Fade,\n        Flip\n    }\n\n    public enum KeyCode\n    {\n        Left  = 0x25,\n        Up    = 0x26,\n        Right = 0x27,\n        Down  = 0x28\n    }\n\n    public enum EaseType\n    {\n        None,\n        BounceEase,\n        CircleEase,\n        CubicEase,\n        ExponentialEase,\n        PowerEase,\n        QuadraticEase,\n        QuarticEase,\n        QuinticEase,\n        SineEase\n    }\n\n    public enum EaseMode\n    {\n        EaseIn,\n        EaseOut,\n        EaseInOut\n    }\n\n    public static class EaseFactory\n    {\n        public static IEasingFunction GetEaseByName( EaseType et, EasingMode em )\n        {\n            IEasingFunction ef = et switch\n            {\n                EaseType.BounceEase => new BounceEase {EasingMode = em},\n                EaseType.CircleEase => new CircleEase {EasingMode = em},\n                EaseType.CubicEase => new CubicEase {EasingMode = em},\n                EaseType.ExponentialEase => new ExponentialEase {EasingMode = em},\n                EaseType.PowerEase => new PowerEase {EasingMode = em},\n                EaseType.QuadraticEase => new QuadraticEase {EasingMode = em},\n                EaseType.QuarticEase => new QuarticEase {EasingMode = em},\n                EaseType.QuinticEase => new QuinticEase {EasingMode = em},\n                EaseType.SineEase => new SineEase {EasingMode = em},\n                EaseType.None => null,\n                _ => null\n            };\n\n            return ef;\n        }\n\n        public static EasingMode GetEaseModeByName( EaseMode em )\n        {\n            var eMode = em switch\n            {\n                EaseMode.EaseIn => EasingMode.EaseIn,\n                EaseMode.EaseOut => EasingMode.EaseOut,\n                EaseMode.EaseInOut => EasingMode.EaseInOut,\n                _ => EasingMode.EaseOut\n            };\n\n            return eMode;\n        }\n    }\n}"
  },
  {
    "path": "Plugins.sln/Cube3D/Effects/Fade.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of Cube3D.\n// \n// Cube3D is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// Cube3D is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with Cube3D. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Windows;\nusing System.Windows.Media;\nusing System.Windows.Media.Animation;\nusing System.Windows.Media.Media3D;\nusing Cube3D.Config;\n\nnamespace Cube3D.Effects\n{\n    public class Fade : Effect\n    {\n        private readonly DoubleAnimation _animationOfFace2 = new()\n        {\n            From = 0,\n            To = 1,\n            FillBehavior = FillBehavior.Stop\n        };\n\n        /////////////////////////////\n        // 重叠的两个面\n        private readonly Model3DGroup    _face      = new();\n        private readonly GeometryModel3D _face1     = new();\n        private readonly MeshGeometry3D  _face1Mesh = new();\n        private readonly GeometryModel3D _face2     = new();\n        private readonly MeshGeometry3D  _face2Mesh = new();\n\n        private readonly ImageBrush _frontD3DImage  = new( D3DImages.D3DImages.FrontD3DImage );\n        private readonly ImageBrush _othersD3DImage = new( D3DImages.D3DImages.OthersD3DImage );\n\n        public Fade()\n        {\n            Animation = new DoubleAnimation\n            {\n                From = 1,\n                To = 0,\n                FillBehavior = FillBehavior.Stop\n            };\n        }\n\n        public override void Build( Model3DGroup model3DGroup )\n        {\n            _face1Mesh.Positions.Add( new Point3D( 0, 0, 0 ) );\n            _face1Mesh.Positions.Add( new Point3D( MeshWidth, 0, 0 ) );\n            _face1Mesh.Positions.Add( new Point3D( MeshWidth, MeshHeight, 0 ) );\n            _face1Mesh.Positions.Add( new Point3D( 0, MeshHeight, 0 ) );\n            AddTriangleIndices( _face1Mesh );\n            AddTextureCoordinatesFront( _face1Mesh );\n\n            _face2Mesh.Positions.Add( new Point3D( 0, 0, 0 ) );\n            _face2Mesh.Positions.Add( new Point3D( MeshWidth, 0, 0 ) );\n            _face2Mesh.Positions.Add( new Point3D( MeshWidth, MeshHeight, 0 ) );\n            _face2Mesh.Positions.Add( new Point3D( 0, MeshHeight, 0 ) );\n            AddTriangleIndices( _face2Mesh );\n            AddTextureCoordinatesFront( _face2Mesh );\n\n            ////////////////////////////////////////////////////////////////\n            // Front 永远显示当前桌面；其在动画中定格，动画结束后归位并继续截屏\n            var frontMaterial = new DiffuseMaterial( _frontD3DImage );\n            _face1.Material = frontMaterial;\n\n            ////////////////////////////////////////////////////////////////\n            // 其他位面永远显示目标桌面，可以共享同一个材质；其在动画中持续截屏，动画结束后归位并停止截屏\n            var othersMaterial = new DiffuseMaterial( _othersD3DImage );\n            _face2.Material = othersMaterial;\n\n            ////////////////////////////////////////////\n            // set GeometryModel3D' mesh\n            _face1.Geometry = _face1Mesh;\n            _face2.Geometry = _face2Mesh;\n\n            ////////////////////////////////////////////\n            // Model3D/Model3DGroup\n            _face.Children.Add( _face2 );\n            _face.Children.Add( _face1 ); // _face1 above _face2\n\n            model3DGroup.Children.Clear();\n            model3DGroup.Children.Add( _face );\n            model3DGroup.Children.Add( CommonLight );\n        }\n\n        public override void AnimationInDirection( KeyCode dir, Model3DGroup model3DGroup, IEasingFunction ef = null )\n        {\n            var animationOfFace1 = (DoubleAnimation)Animation;\n            animationOfFace1.Duration = new Duration( TimeSpan.FromMilliseconds( SettingsManager.Settings.AnimationDuration ) );\n            animationOfFace1.EasingFunction = ef;\n            _animationOfFace2.Duration = animationOfFace1.Duration;\n            _animationOfFace2.EasingFunction = ef;\n\n            _frontD3DImage.BeginAnimation( Brush.OpacityProperty, animationOfFace1 );\n            _othersD3DImage.BeginAnimation( Brush.OpacityProperty, _animationOfFace2 );\n        }\n    }\n}"
  },
  {
    "path": "Plugins.sln/Cube3D/Effects/Flip.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of Cube3D.\n// \n// Cube3D is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// Cube3D is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with Cube3D. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Windows;\nusing System.Windows.Media;\nusing System.Windows.Media.Animation;\nusing System.Windows.Media.Media3D;\nusing Cube3D.Config;\n\nnamespace Cube3D.Effects\n{\n    public class Flip : Effect\n    {\n        private static readonly Dictionary<KeyCode, RotateTransform3D> TransformDirections = new()\n        {\n            {\n                KeyCode.Left, new RotateTransform3D( new AxisAngleRotation3D( new Vector3D( 0, 1, 0 ), 0 ) )\n                {\n                    CenterX = MeshWidth / 2\n                }\n            },\n            {\n                KeyCode.Right, new RotateTransform3D( new AxisAngleRotation3D( new Vector3D( 0, -1, 0 ), 0 ) )\n                {\n                    CenterX = MeshWidth / 2\n                }\n            },\n            {\n                KeyCode.Up, new RotateTransform3D( new AxisAngleRotation3D( new Vector3D( 1, 0, 0 ), 0 ) )\n                {\n                    CenterY = MeshHeight / 2\n                }\n            },\n            {\n                KeyCode.Down, new RotateTransform3D( new AxisAngleRotation3D( new Vector3D( -1, 0, 0 ), 0 ) )\n                {\n                    CenterY = MeshHeight / 2\n                }\n            }\n        };\n\n        /////////////////////////////\n        // 单面翻转\n        private readonly Model3DGroup    _face          = new();\n        private readonly GeometryModel3D _faceFront     = new();\n        private readonly MeshGeometry3D  _faceFrontMesh = new();\n\n        private DiffuseMaterial _backH;\n        private DiffuseMaterial _backV;\n\n        public Flip()\n        {\n            Animation = new DoubleAnimation\n            {\n                From = 0,\n                To = 180,\n                FillBehavior = FillBehavior.Stop\n            };\n        }\n\n        public override void Build( Model3DGroup model3DGroup )\n        {\n            ////////////////////////////////////////////////////////////////\n            // front\n            _faceFrontMesh.Positions.Add( new Point3D( 0, 0, 0 ) );\n            _faceFrontMesh.Positions.Add( new Point3D( MeshWidth, 0, 0 ) );\n            _faceFrontMesh.Positions.Add( new Point3D( MeshWidth, MeshHeight, 0 ) );\n            _faceFrontMesh.Positions.Add( new Point3D( 0, MeshHeight, 0 ) );\n            AddTriangleIndices( _faceFrontMesh );\n            AddTextureCoordinatesFront( _faceFrontMesh );\n\n            ////////////////////////////////////////////////////////////////\n            // Front 永远显示当前桌面；其在动画中定格，动画结束后归位并继续截屏\n            var frontMaterial = new DiffuseMaterial( new ImageBrush( D3DImages.D3DImages.FrontD3DImage ) );\n            _faceFront.Material = frontMaterial;\n\n            ////////////////////////////////////////////////////////////////\n            // Flip 特效利用了 BackMaterial, 水平/垂直翻转的贴图映射需要差异化\n            _backH = new DiffuseMaterial( new ImageBrush( D3DImages.D3DImages.OthersD3DImage )\n            {\n                RelativeTransform = new ScaleTransform\n                {\n                    ScaleX = -1, CenterX = 0.5\n                }\n            } );\n\n            _backV = new DiffuseMaterial( new ImageBrush( D3DImages.D3DImages.OthersD3DImage )\n            {\n                RelativeTransform = new ScaleTransform\n                {\n                    ScaleY = -1, CenterY = 0.5\n                }\n            } );\n\n            ////////////////////////////////////////////\n            // set GeometryModel3D' mesh\n            _faceFront.Geometry = _faceFrontMesh;\n\n            ////////////////////////////////////////////\n            // Model3D/Model3DGroup\n            _face.Children.Add( _faceFront );\n\n            model3DGroup.Children.Clear();\n            model3DGroup.Children.Add( _face );\n            model3DGroup.Children.Add( CommonLight );\n        }\n\n        public override void AnimationInDirection( KeyCode dir, Model3DGroup model3DGroup, IEasingFunction ef = null )\n        {\n            switch ( dir )\n            {\n                case KeyCode.Left:\n                    Transform3D = TransformDirections[KeyCode.Left];\n                    FlipInDirection( \"H\" );\n                    break;\n                case KeyCode.Right:\n                    Transform3D = TransformDirections[KeyCode.Right];\n                    FlipInDirection( \"H\" );\n                    break;\n                case KeyCode.Up:\n                    Transform3D = TransformDirections[KeyCode.Up];\n                    FlipInDirection( \"V\" );\n                    break;\n                case KeyCode.Down:\n                    Transform3D = TransformDirections[KeyCode.Down];\n                    FlipInDirection( \"V\" );\n                    break;\n            }\n\n            if ( TransGroup.Children.Count == 0 )\n            {\n                TransGroup.Children.Add( Transform3D );\n            }\n            else\n            {\n                TransGroup.Children[0] = Transform3D;\n            }\n\n            model3DGroup.Transform = TransGroup;\n\n            var animation = (DoubleAnimation)Animation;\n            animation.Duration = new Duration( TimeSpan.FromMilliseconds( SettingsManager.Settings.AnimationDuration ) );\n            animation.EasingFunction = ef;\n            var transform = (RotateTransform3D)Transform3D;\n            transform.Rotation.BeginAnimation( AxisAngleRotation3D.AngleProperty, animation );\n        }\n\n        private void FlipInDirection( string dir )\n        {\n            _faceFront.BackMaterial = dir == \"H\" ? _backH : _backV;\n        }\n    }\n}"
  },
  {
    "path": "Plugins.sln/Cube3D/Effects/InsideCube.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of Cube3D.\n// \n// Cube3D is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// Cube3D is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with Cube3D. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Windows;\nusing System.Windows.Media;\nusing System.Windows.Media.Animation;\nusing System.Windows.Media.Media3D;\nusing Cube3D.Config;\n\nnamespace Cube3D.Effects\n{\n    public class InsideCube : Effect\n    {\n        private static readonly Dictionary<KeyCode, RotateTransform3D> TransformDirections = new()\n        {\n            {\n                KeyCode.Left,\n                new RotateTransform3D( new AxisAngleRotation3D( new Vector3D( 0, -1, 0 ), 0 ) )\n                {\n                    CenterX = MeshWidth / 2,\n                    CenterZ = MeshWidth / 2\n                }\n            },\n            {\n                KeyCode.Right,\n                new RotateTransform3D( new AxisAngleRotation3D( new Vector3D( 0, 1, 0 ), 0 ) )\n                {\n                    CenterX = MeshWidth / 2,\n                    CenterZ = MeshWidth / 2\n                }\n            },\n            {\n                KeyCode.Up,\n                new RotateTransform3D( new AxisAngleRotation3D( new Vector3D( -1, 0, 0 ), 0 ) )\n                {\n                    CenterY = MeshHeight / 2,\n                    CenterZ = MeshHeight / 2\n                }\n            },\n            {\n                KeyCode.Down,\n                new RotateTransform3D( new AxisAngleRotation3D( new Vector3D( 1, 0, 0 ), 0 ) )\n                {\n                    CenterY = MeshHeight / 2,\n                    CenterZ = MeshHeight / 2\n                }\n            }\n        };\n\n        /////////////////////////////\n        // 立方体\n        // 前/后表面 —— 水平/垂直旋转\n        // 左/右表面 —— 水平旋转\n        // 上/下表面 —— 垂直旋转\n        private readonly Model3DGroup    _cube           = new();\n        private readonly GeometryModel3D _cubeBack       = new();\n        private readonly MeshGeometry3D  _cubeBackMesh   = new();\n        private readonly GeometryModel3D _cubeBottom     = new();\n        private readonly MeshGeometry3D  _cubeBottomMesh = new();\n        private readonly GeometryModel3D _cubeFront      = new();\n        private readonly MeshGeometry3D  _cubeFrontMesh  = new();\n        private readonly GeometryModel3D _cubeLeft       = new();\n        private readonly MeshGeometry3D  _cubeLeftMesh   = new();\n        private readonly GeometryModel3D _cubeRight      = new();\n        private readonly MeshGeometry3D  _cubeRightMesh  = new();\n        private readonly GeometryModel3D _cubeTop        = new();\n        private readonly MeshGeometry3D  _cubeTopMesh    = new();\n\n        public InsideCube()\n        {\n            Animation = new DoubleAnimation\n            {\n                From = 0,\n                To = 90,\n                FillBehavior = FillBehavior.Stop\n            };\n        }\n\n        public override void Build( Model3DGroup model3DGroup )\n        {\n            ////////////////////////////////////////////////////////////////\n            // front\n            _cubeFrontMesh.Positions.Add( new Point3D( 0, 0, 0 ) );\n            _cubeFrontMesh.Positions.Add( new Point3D( MeshWidth, 0, 0 ) );\n            _cubeFrontMesh.Positions.Add( new Point3D( MeshWidth, MeshHeight, 0 ) );\n            _cubeFrontMesh.Positions.Add( new Point3D( 0, MeshHeight, 0 ) );\n            AddTriangleIndices( _cubeFrontMesh );\n            AddTextureCoordinatesFront( _cubeFrontMesh );\n\n            ////////////////////////////////////////////////////////////////\n            // back\n            // _cubeBackMesh.Positions.Add( new Point3D( MeshWidth, 0, MeshWidth ) );\n            // _cubeBackMesh.Positions.Add( new Point3D( 0, 0, MeshWidth ) );\n            // _cubeBackMesh.Positions.Add( new Point3D( 0, MeshHeight, MeshWidth ) );\n            // _cubeBackMesh.Positions.Add( new Point3D( MeshWidth, MeshHeight, MeshWidth ) );\n            // AddTriangleIndices( _cubeBackMesh );\n            // AddTextureCoordinatesFront( _cubeBackMesh );\n\n            //////////////////////////////////////////////////////////////////////////////////////////////////////////\n            // CubeH\n\n            ////////////////////////////////////////////////////////////////\n            // left\n            _cubeLeftMesh.Positions.Add( new Point3D( 0, 0, MeshWidth ) );\n            _cubeLeftMesh.Positions.Add( new Point3D( 0, 0, 0 ) );\n            _cubeLeftMesh.Positions.Add( new Point3D( 0, MeshHeight, 0 ) );\n            _cubeLeftMesh.Positions.Add( new Point3D( 0, MeshHeight, MeshWidth ) );\n            AddTriangleIndices( _cubeLeftMesh );\n            AddTextureCoordinatesFront( _cubeLeftMesh );\n\n            ////////////////////////////////////////////////////////////////\n            // right\n            _cubeRightMesh.Positions.Add( new Point3D( MeshWidth, 0, 0 ) );\n            _cubeRightMesh.Positions.Add( new Point3D( MeshWidth, 0, MeshWidth ) );\n            _cubeRightMesh.Positions.Add( new Point3D( MeshWidth, MeshHeight, MeshWidth ) );\n            _cubeRightMesh.Positions.Add( new Point3D( MeshWidth, MeshHeight, 0 ) );\n            AddTriangleIndices( _cubeRightMesh );\n            AddTextureCoordinatesFront( _cubeRightMesh );\n\n            //////////////////////////////////////////////////////////////////////////////////////////////////////////\n            // CubeV\n\n            ////////////////////////////////////////////////////////////////\n            // top\n            _cubeTopMesh.Positions.Add( new Point3D( 0, MeshHeight, 0 ) );\n            _cubeTopMesh.Positions.Add( new Point3D( MeshWidth, MeshHeight, 0 ) );\n            _cubeTopMesh.Positions.Add( new Point3D( MeshWidth, MeshHeight, MeshHeight ) );\n            _cubeTopMesh.Positions.Add( new Point3D( 0, MeshHeight, MeshHeight ) );\n            AddTriangleIndices( _cubeTopMesh );\n            AddTextureCoordinatesFront( _cubeTopMesh );\n\n            ////////////////////////////////////////////////////////////////\n            // bottom\n            _cubeBottomMesh.Positions.Add( new Point3D( 0, 0, MeshHeight ) );\n            _cubeBottomMesh.Positions.Add( new Point3D( MeshWidth, 0, MeshHeight ) );\n            _cubeBottomMesh.Positions.Add( new Point3D( MeshWidth, 0, 0 ) );\n            _cubeBottomMesh.Positions.Add( new Point3D( 0, 0, 0 ) );\n            AddTriangleIndices( _cubeBottomMesh );\n            AddTextureCoordinatesFront( _cubeBottomMesh );\n\n            ////////////////////////////////////////////////////////////////\n            // Front 永远显示当前桌面；其在动画中定格，动画结束后归位并继续截屏\n            var frontMaterial = new DiffuseMaterial( new ImageBrush( D3DImages.D3DImages.FrontD3DImage ) );\n            _cubeFront.Material = frontMaterial;\n\n            ////////////////////////////////////////////////////////////////\n            // 其他位面永远显示目标桌面，可以共享同一个材质；其在动画中持续截屏，动画结束后归位并停止截屏\n            var othersMaterial = new DiffuseMaterial( new ImageBrush( D3DImages.D3DImages.OthersD3DImage ) );\n\n            // _cubeBack.Material = othersMaterial;\n            _cubeLeft.Material = othersMaterial;\n            _cubeRight.Material = othersMaterial;\n            _cubeTop.Material = othersMaterial;\n            _cubeBottom.Material = othersMaterial;\n\n            ////////////////////////////////////////////\n            // set GeometryModel3D' mesh\n            _cubeFront.Geometry = _cubeFrontMesh;\n            // _cubeBack.Geometry = _cubeBackMesh;\n            _cubeLeft.Geometry = _cubeLeftMesh;\n            _cubeRight.Geometry = _cubeRightMesh;\n            _cubeTop.Geometry = _cubeTopMesh;\n            _cubeBottom.Geometry = _cubeBottomMesh;\n\n            ////////////////////////////////////////////\n            // Model3D/Model3DGroup\n            _cube.Children.Add( _cubeFront );\n            // _cube.Children.Add( _cubeBack );\n            _cube.Children.Add( _cubeLeft );\n            _cube.Children.Add( _cubeRight );\n            _cube.Children.Add( _cubeTop );\n            _cube.Children.Add( _cubeBottom );\n\n            model3DGroup.Children.Clear();\n            model3DGroup.Children.Add( _cube );\n            model3DGroup.Children.Add( CommonLight );\n        }\n\n        public override void AnimationInDirection( KeyCode dir, Model3DGroup model3DGroup, IEasingFunction ef = null )\n        {\n            switch ( dir )\n            {\n                case KeyCode.Left:\n                    Transform3D = TransformDirections[KeyCode.Left];\n                    break;\n                case KeyCode.Right:\n                    Transform3D = TransformDirections[KeyCode.Right];\n                    break;\n                case KeyCode.Up:\n                    Transform3D = TransformDirections[KeyCode.Up];\n                    break;\n                case KeyCode.Down:\n                    Transform3D = TransformDirections[KeyCode.Down];\n                    break;\n            }\n\n            if ( TransGroup.Children.Count == 0 )\n            {\n                TransGroup.Children.Add( Transform3D );\n            }\n            else\n            {\n                TransGroup.Children[0] = Transform3D;\n            }\n\n            model3DGroup.Transform = TransGroup;\n\n            var animation = (DoubleAnimation)Animation;\n            animation.Duration = new Duration( TimeSpan.FromMilliseconds( SettingsManager.Settings.AnimationDuration ) );\n            animation.EasingFunction = ef;\n            var transform = (RotateTransform3D)Transform3D;\n            transform.Rotation.BeginAnimation( AxisAngleRotation3D.AngleProperty, animation );\n        }\n    }\n}"
  },
  {
    "path": "Plugins.sln/Cube3D/Effects/Reveal.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of Cube3D.\n// \n// Cube3D is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// Cube3D is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with Cube3D. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Windows;\nusing System.Windows.Media;\nusing System.Windows.Media.Animation;\nusing System.Windows.Media.Media3D;\nusing Cube3D.Config;\n\nnamespace Cube3D.Effects\n{\n    public class Reveal : Effect\n    {\n        private static readonly Dictionary<KeyCode, TranslateTransform3D> TransformDirections = new()\n        {\n            {\n                KeyCode.Left, new TranslateTransform3D()\n            },\n            {\n                KeyCode.Right, new TranslateTransform3D()\n            },\n            {\n                KeyCode.Up, new TranslateTransform3D()\n            },\n            {\n                KeyCode.Down, new TranslateTransform3D()\n            }\n        };\n\n        /////////////////////////////\n        // 重叠的两个面\n        private readonly Model3DGroup    _face      = new();\n        private readonly GeometryModel3D _face1     = new();\n        private readonly MeshGeometry3D  _face1Mesh = new();\n        private readonly GeometryModel3D _face2     = new();\n        private readonly MeshGeometry3D  _face2Mesh = new();\n\n        public Reveal()\n        {\n            Animation = new DoubleAnimation\n            {\n                From = 0,\n                FillBehavior = FillBehavior.Stop\n            };\n        }\n\n        public override void Build( Model3DGroup model3DGroup )\n        {\n            _face1Mesh.Positions.Add( new Point3D( 0, 0, 0 ) );\n            _face1Mesh.Positions.Add( new Point3D( MeshWidth, 0, 0 ) );\n            _face1Mesh.Positions.Add( new Point3D( MeshWidth, MeshHeight, 0 ) );\n            _face1Mesh.Positions.Add( new Point3D( 0, MeshHeight, 0 ) );\n            AddTriangleIndices( _face1Mesh );\n            AddTextureCoordinatesFront( _face1Mesh );\n\n            _face2Mesh.Positions.Add( new Point3D( 0, 0, 0 ) );\n            _face2Mesh.Positions.Add( new Point3D( MeshWidth, 0, 0 ) );\n            _face2Mesh.Positions.Add( new Point3D( MeshWidth, MeshHeight, 0 ) );\n            _face2Mesh.Positions.Add( new Point3D( 0, MeshHeight, 0 ) );\n            AddTriangleIndices( _face2Mesh );\n            AddTextureCoordinatesFront( _face2Mesh );\n\n            ////////////////////////////////////////////////////////////////\n            // Front 永远显示当前桌面；其在动画中定格，动画结束后归位并继续截屏\n            var frontMaterial = new DiffuseMaterial( new ImageBrush( D3DImages.D3DImages.FrontD3DImage ) );\n            _face1.Material = frontMaterial;\n\n            ////////////////////////////////////////////////////////////////\n            // 其他位面永远显示目标桌面，可以共享同一个材质；其在动画中持续截屏，动画结束后归位并停止截屏\n            var othersMaterial = new DiffuseMaterial( new ImageBrush( D3DImages.D3DImages.OthersD3DImage ) );\n            _face2.Material = othersMaterial;\n\n            ////////////////////////////////////////////\n            // set GeometryModel3D' mesh\n            _face1.Geometry = _face1Mesh;\n            _face2.Geometry = _face2Mesh;\n\n            ////////////////////////////////////////////\n            // Model3D/Model3DGroup\n            _face.Children.Add( _face2 );\n            _face.Children.Add( _face1 ); // _face1 above _face2\n\n            model3DGroup.Children.Clear();\n            model3DGroup.Children.Add( _face );\n            model3DGroup.Children.Add( CommonLight );\n        }\n\n        public override void AnimationInDirection( KeyCode dir, Model3DGroup model3DGroup, IEasingFunction ef = null )\n        {\n            var offsetProperty = TranslateTransform3D.OffsetXProperty;\n            var animation      = (DoubleAnimation)Animation;\n            animation.Duration = new Duration( TimeSpan.FromMilliseconds( SettingsManager.Settings.AnimationDuration ) );\n            animation.EasingFunction = ef;\n\n            switch ( dir )\n            {\n                case KeyCode.Left:\n                    Transform3D = TransformDirections[KeyCode.Left];\n                    animation.To = MeshWidth;\n                    break;\n                case KeyCode.Right:\n                    Transform3D = TransformDirections[KeyCode.Right];\n                    animation.To = -MeshWidth;\n                    break;\n                case KeyCode.Up:\n                    Transform3D = TransformDirections[KeyCode.Up];\n                    animation.To = -MeshHeight;\n                    offsetProperty = TranslateTransform3D.OffsetYProperty;\n                    break;\n                case KeyCode.Down:\n                    Transform3D = TransformDirections[KeyCode.Down];\n                    animation.To = MeshHeight;\n                    offsetProperty = TranslateTransform3D.OffsetYProperty;\n                    break;\n            }\n\n            if ( TransGroup.Children.Count == 0 )\n            {\n                TransGroup.Children.Add( Transform3D );\n            }\n            else\n            {\n                TransGroup.Children[0] = Transform3D;\n            }\n\n            _face1.Transform = TransGroup;\n\n            var transform = (TranslateTransform3D)Transform3D;\n            transform.BeginAnimation( offsetProperty, animation );\n        }\n    }\n}"
  },
  {
    "path": "Plugins.sln/Cube3D/Effects/Slide.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of Cube3D.\n// \n// Cube3D is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// Cube3D is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with Cube3D. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Windows;\nusing System.Windows.Media;\nusing System.Windows.Media.Animation;\nusing System.Windows.Media.Media3D;\nusing Cube3D.Config;\n\nnamespace Cube3D.Effects\n{\n    public class Slide : Effect\n    {\n        private static readonly Dictionary<KeyCode, TranslateTransform3D> TransformDirections = new()\n        {\n            {\n                KeyCode.Left, new TranslateTransform3D()\n            },\n            {\n                KeyCode.Right, new TranslateTransform3D()\n            },\n            {\n                KeyCode.Up, new TranslateTransform3D()\n            },\n            {\n                KeyCode.Down, new TranslateTransform3D()\n            }\n        };\n\n        /////////////////////////////\n        // 十字排列的五个全等面\n        private readonly Model3DGroup    _face           = new();\n        private readonly GeometryModel3D _faceBottom     = new();\n        private readonly MeshGeometry3D  _faceBottomMesh = new();\n        private readonly GeometryModel3D _faceCenter     = new();\n        private readonly MeshGeometry3D  _faceCenterMesh = new();\n        private readonly GeometryModel3D _faceLeft       = new();\n        private readonly MeshGeometry3D  _faceLeftMesh   = new();\n        private readonly GeometryModel3D _faceRight      = new();\n        private readonly MeshGeometry3D  _faceRightMesh  = new();\n        private readonly GeometryModel3D _faceTop        = new();\n        private readonly MeshGeometry3D  _faceTopMesh    = new();\n\n        public Slide()\n        {\n            Animation = new DoubleAnimation\n            {\n                From = 0,\n                FillBehavior = FillBehavior.Stop\n            };\n        }\n\n        public override void Build( Model3DGroup model3DGroup )\n        {\n            ////////////////////////////////////////////////////////////////\n            // center\n            var centerPoints = new Point3D[]\n            {\n                new( 0, 0, 0 ),\n                new( MeshWidth, 0, 0 ),\n                new( MeshWidth, MeshHeight, 0 ),\n                new( 0, MeshHeight, 0 )\n            };\n            _faceCenterMesh.Positions.Add( centerPoints[0] );\n            _faceCenterMesh.Positions.Add( centerPoints[1] );\n            _faceCenterMesh.Positions.Add( centerPoints[2] );\n            _faceCenterMesh.Positions.Add( centerPoints[3] );\n            AddTriangleIndices( _faceCenterMesh );\n            AddTextureCoordinatesFront( _faceCenterMesh );\n\n            ////////////////////////////////////////////////////////////////\n            // left\n            var left = new Vector3D( -MeshWidth, 0, 0 );\n            _faceLeftMesh.Positions.Add( centerPoints[0] + left );\n            _faceLeftMesh.Positions.Add( centerPoints[1] + left );\n            _faceLeftMesh.Positions.Add( centerPoints[2] + left );\n            _faceLeftMesh.Positions.Add( centerPoints[3] + left );\n            AddTriangleIndices( _faceLeftMesh );\n            AddTextureCoordinatesFront( _faceLeftMesh );\n\n            ////////////////////////////////////////////////////////////////\n            // right\n            var right = new Vector3D( MeshWidth, 0, 0 );\n            _faceRightMesh.Positions.Add( centerPoints[0] + right );\n            _faceRightMesh.Positions.Add( centerPoints[1] + right );\n            _faceRightMesh.Positions.Add( centerPoints[2] + right );\n            _faceRightMesh.Positions.Add( centerPoints[3] + right );\n            AddTriangleIndices( _faceRightMesh );\n            AddTextureCoordinatesFront( _faceRightMesh );\n\n            ////////////////////////////////////////////////////////////////\n            // top\n            var top = new Vector3D( 0, MeshHeight, 0 );\n            _faceTopMesh.Positions.Add( centerPoints[0] + top );\n            _faceTopMesh.Positions.Add( centerPoints[1] + top );\n            _faceTopMesh.Positions.Add( centerPoints[2] + top );\n            _faceTopMesh.Positions.Add( centerPoints[3] + top );\n            AddTriangleIndices( _faceTopMesh );\n            AddTextureCoordinatesFront( _faceTopMesh );\n\n            ////////////////////////////////////////////////////////////////\n            // bottom\n            var bottom = new Vector3D( 0, -MeshHeight, 0 );\n            _faceBottomMesh.Positions.Add( centerPoints[0] + bottom );\n            _faceBottomMesh.Positions.Add( centerPoints[1] + bottom );\n            _faceBottomMesh.Positions.Add( centerPoints[2] + bottom );\n            _faceBottomMesh.Positions.Add( centerPoints[3] + bottom );\n            AddTriangleIndices( _faceBottomMesh );\n            AddTextureCoordinatesFront( _faceBottomMesh );\n\n            ////////////////////////////////////////////////////////////////\n            // Front 永远显示当前桌面；其在动画中定格，动画结束后归位并继续截屏\n            var frontMaterial = new DiffuseMaterial( new ImageBrush( D3DImages.D3DImages.FrontD3DImage ) );\n            _faceCenter.Material = frontMaterial;\n\n            ////////////////////////////////////////////////////////////////\n            // 其他位面永远显示目标桌面，可以共享同一个材质；其在动画中持续截屏，动画结束后归位并停止截屏\n            var othersMaterial = new DiffuseMaterial( new ImageBrush( D3DImages.D3DImages.OthersD3DImage ) );\n            _faceLeft.Material = othersMaterial;\n            _faceRight.Material = othersMaterial;\n            _faceTop.Material = othersMaterial;\n            _faceBottom.Material = othersMaterial;\n\n            ////////////////////////////////////////////\n            // set GeometryModel3D' mesh\n            _faceCenter.Geometry = _faceCenterMesh;\n            _faceLeft.Geometry = _faceLeftMesh;\n            _faceRight.Geometry = _faceRightMesh;\n            _faceTop.Geometry = _faceTopMesh;\n            _faceBottom.Geometry = _faceBottomMesh;\n\n            ////////////////////////////////////////////\n            // Model3D/Model3DGroup\n            _face.Children.Add( _faceCenter );\n            _face.Children.Add( _faceLeft );\n            _face.Children.Add( _faceRight );\n            _face.Children.Add( _faceTop );\n            _face.Children.Add( _faceBottom );\n\n            model3DGroup.Children.Clear();\n            model3DGroup.Children.Add( _face );\n            model3DGroup.Children.Add( CommonLight );\n        }\n\n        public override void AnimationInDirection( KeyCode dir, Model3DGroup model3DGroup, IEasingFunction ef = null )\n        {\n            var offsetProperty = TranslateTransform3D.OffsetXProperty;\n            var animation      = (DoubleAnimation)Animation;\n            animation.Duration = new Duration( TimeSpan.FromMilliseconds( SettingsManager.Settings.AnimationDuration ) );\n            animation.EasingFunction = ef;\n\n            switch ( dir )\n            {\n                case KeyCode.Left:\n                    Transform3D = TransformDirections[KeyCode.Left];\n                    animation.To = MeshWidth;\n                    break;\n                case KeyCode.Right:\n                    Transform3D = TransformDirections[KeyCode.Right];\n                    animation.To = -MeshWidth;\n                    break;\n                case KeyCode.Up:\n                    Transform3D = TransformDirections[KeyCode.Up];\n                    animation.To = -MeshHeight;\n                    offsetProperty = TranslateTransform3D.OffsetYProperty;\n                    break;\n                case KeyCode.Down:\n                    Transform3D = TransformDirections[KeyCode.Down];\n                    animation.To = MeshHeight;\n                    offsetProperty = TranslateTransform3D.OffsetYProperty;\n                    break;\n            }\n\n            if ( TransGroup.Children.Count == 0 )\n            {\n                TransGroup.Children.Add( Transform3D );\n            }\n            else\n            {\n                TransGroup.Children[0] = Transform3D;\n            }\n\n            model3DGroup.Transform = TransGroup;\n\n            var transform = (TranslateTransform3D)Transform3D;\n            transform.BeginAnimation( offsetProperty, animation );\n        }\n    }\n}"
  },
  {
    "path": "Plugins.sln/Cube3D/FrameToD3DImage.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of Cube3D.\n\nCube3D is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nCube3D is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with Cube3D. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Collections.Generic;\nusing System.Windows;\nusing System.Windows.Interop;\nusing System.Windows.Media;\nusing Cube3D.Config;\nusing ScreenCapture;\n\nnamespace Cube3D\n{\n    public class FrameToD3DImage : FrameProcessor\n    {\n        private readonly Dictionary<string, D3DImageInfo> _d3DImageDict;\n        private readonly Duration                         _duration = new( new TimeSpan( 0, 0, 0, 0, 5 ) );\n        private          Action                           _animation;\n\n        private FrameToD3DImage()\n        {\n        }\n\n        public FrameToD3DImage( Dictionary<string, D3DImageInfo> d3dImageDict )\n        {\n            _d3DImageDict = d3dImageDict;\n        }\n\n        public void SetAction( Action action )\n        {\n            _animation = action;\n        }\n\n        public override void Proceed( IntPtr pointer, ulong frameNumber )\n        {\n            if ( frameNumber == 1 )\n            {\n                Paint( _d3DImageDict[Const.Front], pointer );\n            }\n            else\n            {\n                if ( frameNumber == 2 )\n                {\n                    _animation?.Invoke();\n                }\n\n                Paint( _d3DImageDict[Const.Others], pointer );\n            }\n        }\n\n        private void Paint( D3DImageInfo dii, IntPtr pointer )\n        {\n            var useSoftRender = IsSoftRender();\n\n            var d3DImage = dii.Image;\n\n            if ( !useSoftRender && !d3DImage.IsFrontBufferAvailable ) return;\n\n            if ( d3DImage.TryLock( _duration ) )\n            {\n                d3DImage.SetBackBuffer( D3DResourceType.IDirect3DSurface9, pointer, useSoftRender );\n                d3DImage.AddDirtyRect( new Int32Rect( 0, 0, d3DImage.PixelWidth, d3DImage.PixelHeight ) );\n            }\n\n            d3DImage.Unlock();\n        }\n\n        private static bool IsSoftRender()\n        {\n            var level = RenderCapability.Tier >> 16;\n            return level == 0;\n        }\n    }\n\n    public class D3DImageInfo\n    {\n        public D3DImage Image { get; set; }\n    }\n}"
  },
  {
    "path": "Plugins.sln/Cube3D/Helpers/User32.cs",
    "content": "﻿using System;\nusing System.Runtime.InteropServices;\nusing System.Text;\n\nnamespace VirtualSpace.Helpers\n{\n    public static class User32\n    {\n        public delegate bool EnumWindowsProc( IntPtr hWnd, int lParam );\n\n        public enum MonitorDpiType\n        {\n            MDT_EFFECTIVE_DPI = 0,\n            MDT_ANGULAR_DPI   = 1,\n            MDT_RAW_DPI       = 2\n        }\n\n        [Flags]\n        public enum SetWindowPosFlags : uint\n        {\n            // ReSharper disable InconsistentNaming\n\n            /// <summary>\n            ///     If the calling thread and the thread that owns the window are attached to different input queues, the system posts the request to the thread that owns the window. This\n            ///     prevents the calling thread from blocking its execution while other threads process the request.\n            /// </summary>\n            SWP_ASYNCWINDOWPOS = 0x4000,\n\n            /// <summary>\n            ///     Prevents generation of the WM_SYNCPAINT message.\n            /// </summary>\n            SWP_DEFERERASE = 0x2000,\n\n            /// <summary>\n            ///     Draws a frame (defined in the window's class description) around the window.\n            /// </summary>\n            SWP_DRAWFRAME = 0x0020,\n\n            /// <summary>\n            ///     Applies new frame styles set using the SetWindowLong function. Sends a WM_NCCALCSIZE message to the window, even if the window's size is not being changed. If this flag is not\n            ///     specified, WM_NCCALCSIZE is sent only when the window's size is being changed.\n            /// </summary>\n            SWP_FRAMECHANGED = 0x0020,\n\n            /// <summary>\n            ///     Hides the window.\n            /// </summary>\n            SWP_HIDEWINDOW = 0x0080,\n\n            /// <summary>\n            ///     Does not activate the window. If this flag is not set, the window is activated and moved to the top of either the topmost or non-topmost group (depending on the setting of the\n            ///     hWndInsertAfter parameter).\n            /// </summary>\n            SWP_NOACTIVATE = 0x0010,\n\n            /// <summary>\n            ///     Discards the entire contents of the client area. If this flag is not specified, the valid contents of the client area are saved and copied back into the client area after the\n            ///     window is sized or repositioned.\n            /// </summary>\n            SWP_NOCOPYBITS = 0x0100,\n\n            /// <summary>\n            ///     Retains the current position (ignores X and Y parameters).\n            /// </summary>\n            SWP_NOMOVE = 0x0002,\n\n            /// <summary>\n            ///     Does not change the owner window's position in the Z order.\n            /// </summary>\n            SWP_NOOWNERZORDER = 0x0200,\n\n            /// <summary>\n            ///     Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies to the client area, the nonclient area (including the title bar and scroll bars),\n            ///     and any part of the parent window uncovered as a result of the window being moved. When this flag is set, the application must explicitly invalidate or redraw any parts of the\n            ///     window and parent window that need redrawing.\n            /// </summary>\n            SWP_NOREDRAW = 0x0008,\n\n            /// <summary>\n            ///     Same as the SWP_NOOWNERZORDER flag.\n            /// </summary>\n            SWP_NOREPOSITION = 0x0200,\n\n            /// <summary>\n            ///     Prevents the window from receiving the WM_WINDOWPOSCHANGING message.\n            /// </summary>\n            SWP_NOSENDCHANGING = 0x0400,\n\n            /// <summary>\n            ///     Retains the current size (ignores the cx and cy parameters).\n            /// </summary>\n            SWP_NOSIZE = 0x0001,\n\n            /// <summary>\n            ///     Retains the current Z order (ignores the hWndInsertAfter parameter).\n            /// </summary>\n            SWP_NOZORDER = 0x0004,\n\n            /// <summary>\n            ///     Displays the window.\n            /// </summary>\n            SWP_SHOWWINDOW = 0x0040\n        }\n\n        /// <summary>\n        ///     Special window handles\n        /// </summary>\n        public enum SpecialWindowHandles\n        {\n            // ReSharper disable InconsistentNaming\n            /// <summary>\n            ///     Places the window at the top of the Z order.\n            /// </summary>\n            HWND_TOP = 0,\n\n            /// <summary>\n            ///     Places the window at the bottom of the Z order. If the hWnd parameter identifies a topmost window, the window loses its topmost status and is placed at the bottom of all other\n            ///     windows.\n            /// </summary>\n            HWND_BOTTOM = 1,\n\n            /// <summary>\n            ///     Places the window above all non-topmost windows. The window maintains its topmost position even when it is deactivated.\n            /// </summary>\n            HWND_TOPMOST = -1,\n\n            /// <summary>\n            ///     Places the window above all non-topmost windows (that is, behind all topmost windows). This flag has no effect if the window is already a non-topmost window.\n            /// </summary>\n            HWND_NOTOPMOST = -2\n            // ReSharper restore InconsistentNaming\n        }\n\n        public const uint WDA_EXCLUDEFROMCAPTURE = 0x00000011;\n\n        [DllImport( \"user32.dll\" )]\n        public static extern uint SetWindowDisplayAffinity( IntPtr hWnd, uint dwAffinity );\n\n        [DllImport( \"user32.dll\", CharSet = CharSet.Auto )]\n        public static extern int GetWindowLong( IntPtr hWnd, int nIndex );\n\n        public static IntPtr SetWindowLongPtr( HandleRef hWnd, int nIndex, int dwNewLong )\n        {\n            if ( IntPtr.Size == 8 )\n                return SetWindowLongPtr64( hWnd, nIndex, (IntPtr)dwNewLong );\n            else\n                return new IntPtr( SetWindowLong32( hWnd, nIndex, dwNewLong ) );\n        }\n\n        [DllImport( \"user32.dll\", EntryPoint = \"SetWindowLong\" )]\n        private static extern int SetWindowLong32( HandleRef hWnd, int nIndex, int dwNewLong );\n\n        [DllImport( \"user32.dll\", EntryPoint = \"SetWindowLongPtr\" )]\n        private static extern IntPtr SetWindowLongPtr64( HandleRef hWnd, int nIndex, IntPtr dwNewLong );\n\n        [DllImport( \"user32.dll\", SetLastError = true )]\n        public static extern bool SetWindowPos( IntPtr hWnd, SpecialWindowHandles hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags );\n\n        [DllImport( \"user32.dll\" )]\n        public static extern bool IsWindowVisible( IntPtr hWnd );\n\n        [DllImport( \"user32.dll\" )]\n        public static extern int EnumWindows( EnumWindowsProc func, int lParam );\n\n        [DllImport( \"user32.dll\" )]\n        public static extern int GetWindowText( IntPtr hWnd, StringBuilder buf, int nMaxCount );\n\n        [DllImport( \"shcore.dll\" )]\n        public static extern uint GetDpiForMonitor( IntPtr hmonitor, MonitorDpiType dpiType, out uint dpiX, out uint dpiY );\n    }\n}"
  },
  {
    "path": "Plugins.sln/Cube3D/Helpers/Win32.cs",
    "content": "﻿using System;\nusing System.Runtime.InteropServices;\n\nnamespace VirtualSpace.Helpers\n{\n    public enum GetWindowLongFields\n    {\n        GWL_USERDATA   = -21, // 0xFFFFFFEB\n        GWL_EXSTYLE    = -20, // 0xFFFFFFEC\n        GWL_STYLE      = -16, // 0xFFFFFFF0\n        GWL_ID         = -12, // 0xFFFFFFF4\n        GWL_HWNDPARENT = -8, // 0xFFFFFFF8\n        GWL_HINSTANCE  = -6, // 0xFFFFFFFA\n        GWL_WNDPROC    = -4 // 0xFFFFFFFC\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct INPUT\n    {\n        public uint                    Type;\n        public MOUSEKEYBDHARDWAREINPUT Data;\n    }\n\n    [StructLayout( LayoutKind.Explicit )]\n    public struct MOUSEKEYBDHARDWAREINPUT\n    {\n        [FieldOffset( 0 )] public HARDWAREINPUT Hardware;\n        [FieldOffset( 0 )] public KEYBDINPUT    Keyboard;\n        [FieldOffset( 0 )] public MOUSEINPUT    Mouse;\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct HARDWAREINPUT\n    {\n        public uint   Msg;\n        public ushort ParamL;\n        public ushort ParamH;\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct KEYBDINPUT\n    {\n        public ushort Vk;\n        public ushort Scan;\n        public uint   Flags;\n        public uint   Time;\n        public IntPtr ExtraInfo;\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct MOUSEINPUT\n    {\n        public int    X;\n        public int    Y;\n        public uint   MouseData;\n        public uint   Flags;\n        public uint   Time;\n        public IntPtr ExtraInfo;\n    }\n}"
  },
  {
    "path": "Plugins.sln/Cube3D/Helpers/WinMsg.cs",
    "content": "﻿namespace VirtualSpace.Helpers\n{\n    public static class WinMsg\n    {\n        public const int WM_SYSCOMMAND    = 0x0112;\n        public const int SC_MAXIMIZE      = 0xF030;\n        public const int SC_MINIMIZE      = 0xF020;\n        public const int SC_RESTORE       = 0xF120;\n        public const int SC_SIZE          = 0xF000;\n        public const int SC_MOVE          = 0xF010;\n        public const int SC_CLOSE         = 0xF060;\n        public const int WM_HOTKEY        = 0x0312;\n        public const int WM_CLOSE         = 0x0010;\n        public const int WM_QUIT          = 0x0012;\n        public const int WM_DESTROY       = 0x0002;\n        public const int WM_MOUSEACTIVATE = 0x0021;\n        public const int MA_NOACTIVATE    = 0x3;\n        public const int WM_DISPLAYCHANGE = 0x007E;\n    }\n}"
  },
  {
    "path": "Plugins.sln/Cube3D/Helpers/WpfConverters.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of Plugins.\n// \n// Plugins is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// Plugins is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with Plugins. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Globalization;\nusing System.Windows.Data;\nusing Cube3D.Config;\n\nnamespace VirtualSpace.Helpers\n{\n    public class TransitionTypeConverter : IValueConverter\n    {\n        public object Convert( object value, Type targetType, object parameters, CultureInfo culture )\n        {\n            if ( value is null ) return null;\n\n            var t = (TransitionType)value;\n\n            return ( t & TransitionType.NotificationGridOnly ) > 0;\n        }\n\n        public object ConvertBack( object value, Type targetType, object parameters, CultureInfo culture )\n        {\n            throw new NotImplementedException();\n        }\n    }\n}"
  },
  {
    "path": "Plugins.sln/Cube3D/MainWindow.2D.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of Cube3D.\n\nCube3D is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nCube3D is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with Cube3D. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Windows;\nusing System.Windows.Controls;\n\nnamespace Cube3D\n{\n    public partial class MainWindow\n    {\n        private void NotificationGridLayout( int vdCount )\n        {\n            ////////////////////////////////////////////////////////////////\n            // position and size\n            var screenW = SystemParameters.PrimaryScreenWidth;\n            var screenH = SystemParameters.PrimaryScreenHeight;\n            var centerX = screenW / 2;\n            var centerY = screenH * 5 / 16;\n            NotifyContainer.Width = screenW / 6;\n            NotifyContainer.Height = NotifyContainer.Width * 3 / 4;\n            NotifyContainer.Margin = new Thickness\n            {\n                Top = centerY + NotifyContainer.Height\n            };\n\n            ////////////////////////////////////////////////////////////////\n            // contents\n            var rowsCols = (int)Math.Ceiling( Math.Sqrt( vdCount ) );\n            var maxCount = rowsCols * rowsCols;\n            if ( NotifyGrid.Children.Count != maxCount )\n            {\n                NotifyGrid.Children.Clear();\n                for ( var i = 0; i < maxCount; i++ )\n                {\n                    NotifyGrid.Children.Add( new Button\n                    {\n                        // Content = i.ToString(),\n                        Template = Resources[\"NotifyButtonTemplate\"] as ControlTemplate\n                    } );\n                }\n            }\n\n            UpdateLayout();\n            var firstCell = (Button)NotifyGrid.Children[0]; // 因为至少有一个桌面，所以 0 索引子元素必然存在\n            var buttonMargin = new Thickness\n            {\n                Left = firstCell.ActualWidth / 10.0,\n                Top = firstCell.ActualHeight / 10.0\n            };\n\n            Resources[\"NotifyButtonMargin\"] = buttonMargin;\n            NotifyBorder.Padding = new Thickness {Right = buttonMargin.Left, Bottom = buttonMargin.Top};\n\n            UpdateLayout();\n\n            CurrentIndicator.Width = firstCell.ActualWidth;\n            CurrentIndicator.Height = firstCell.ActualHeight;\n        }\n    }\n}"
  },
  {
    "path": "Plugins.sln/Cube3D/MainWindow.3D.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of Cube3D.\n\nCube3D is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nCube3D is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with Cube3D. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Windows.Media.Media3D;\nusing Cube3D.Config;\nusing Cube3D.Effects;\nusing ScreenCapture;\n\nnamespace Cube3D\n{\n    public partial class MainWindow\n    {\n        private static Effect _effect;\n\n        private void CameraPosition( MonitorInfo mi )\n        {\n            var ratio          = mi.ScreenSize.Y / mi.ScreenSize.X;\n            var workAreaWidth  = 1.0;\n            var workAreaHeight = workAreaWidth * ratio;\n            var radianFov      = MainCamera.FieldOfView * ( Math.PI / 180 );\n            var cameraX        = workAreaWidth / 2;\n            var cameraY        = workAreaHeight / 2;\n            var cameraZ        = workAreaWidth / 2 / Math.Tan( radianFov / 2 );\n            MainCamera = new PerspectiveCamera\n            {\n                LookDirection = new Vector3D( 0, 0, -1 ),\n                Position = new Point3D( cameraX, cameraY, cameraZ )\n            };\n            Vp3D.Camera = MainCamera;\n        }\n\n        public void Build3D()\n        {\n            var settings = SettingsManager.Settings;\n            _effect = settings.SelectedEffect switch\n            {\n                EffectType.Cube => new Cube(),\n                EffectType.Flip => new Flip(),\n                EffectType.Slide => new Slide(),\n                EffectType.Reveal => new Reveal(),\n                EffectType.Fade => new Fade(),\n                EffectType.InsideCube => new InsideCube(),\n                _ => new Cube()\n            };\n\n            _effect.Build( MainModel3DGroup );\n            _effect.AddAnimationCompletedListener( AnimationCompleted );\n        }\n    }\n}"
  },
  {
    "path": "Plugins.sln/Cube3D/MainWindow.animation.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of Cube3D.\n\nCube3D is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nCube3D is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with Cube3D. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Threading;\nusing System.Windows;\nusing System.Windows.Controls;\nusing System.Windows.Media.Animation;\nusing System.Windows.Media.Media3D;\nusing Cube3D.Config;\n\nnamespace Cube3D\n{\n    public partial class MainWindow\n    {\n        private static long _mainWindowRunningAnimationCount;\n\n        private readonly ThicknessAnimation _animationNotifyGrid = new()\n        {\n            FillBehavior = FillBehavior.Stop\n        };\n\n        private void AnimationCompleted( object sender, EventArgs e )\n        {\n            if ( _monitorInfo.IsPrimary )\n            {\n                Interlocked.Decrement( ref _mainWindowRunningAnimationCount );\n                if ( _mainWindowRunningAnimationCount == 0 )\n                    FakeHide( true );\n            }\n            else\n            {\n                FakeHide( true );\n            }\n        }\n\n        private void NotificationGridAnimation( int fromIndex, int toIndex, int vdCount, IEasingFunction ef = null )\n        {\n            var oneCell = (Button)NotifyGrid.Children[fromIndex]; // 用 0 也行，UniformGrid 的 cell 尺寸一样\n\n            var rowsCols = (int)Math.Ceiling( Math.Sqrt( vdCount ) );\n            var fromRow  = fromIndex / rowsCols; // divide\n            var fromCol  = fromIndex % rowsCols; // modulus \n            var toRow    = toIndex / rowsCols; // divide\n            var toCol    = toIndex % rowsCols; // modulus \n\n            var buttonMargin = (Thickness)Resources[\"NotifyButtonMargin\"];\n\n            var cellCenterToCell00Distance = rowsCols - 1; // 默认 margin all=0 在中心，需计算与左上角的单位距离\n            var cell00Margin = new Thickness // 左上角 cell 的 margin，行索引=列索引=子元素索引=0，便于计算\n            {\n                Left = -buttonMargin.Left - cellCenterToCell00Distance * oneCell.ActualWidth,\n                Top = -buttonMargin.Top - cellCenterToCell00Distance * oneCell.ActualHeight\n            };\n\n            ///////////////////////////////////////////////////////////////////\n            // 所有非 0 索引的 cell，其 margin 都基于左上角 cell 计算，籍此进行定位\n            CurrentIndicator.Margin = new Thickness // 当前索引作为动画起始 cell\n            {\n                Left = cell00Margin.Left + 2 * fromCol * oneCell.ActualWidth, // 宽度对应列系数\n                Top = cell00Margin.Top + 2 * fromRow * oneCell.ActualHeight // 高度对应行系数\n            };\n\n            var targetCellMargin = new Thickness // 目标 cell 作为动画结束 cell\n            {\n                Left = cell00Margin.Left + 2 * toCol * oneCell.ActualWidth, // 宽度对应列系数\n                Top = cell00Margin.Top + 2 * toRow * oneCell.ActualHeight // 高度对应行系数\n            };\n\n            ////////////////////////////////////////////////////////////////\n            // animation\n            _animationNotifyGrid.From = CurrentIndicator.Margin;\n            _animationNotifyGrid.To = targetCellMargin;\n            _animationNotifyGrid.Duration = new Duration( TimeSpan.FromMilliseconds( SettingsManager.Settings.AnimationDuration ) );\n            _animationNotifyGrid.EasingFunction = ef;\n            CurrentIndicator.BeginAnimation( MarginProperty, _animationNotifyGrid );\n        }\n\n        private void CameraAnimation()\n        {\n            var animationCamera = new Point3DAnimation\n            {\n                From = new Point3D( MainCamera.Position.X, MainCamera.Position.Y, MainCamera.Position.Z + 0.1 ),\n                To = new Point3D( MainCamera.Position.X, MainCamera.Position.Y, MainCamera.Position.Z + 0.5 ),\n                Duration = new Duration( TimeSpan.FromMilliseconds( SettingsManager.Settings.AnimationDuration / 2.0 ) ),\n                FillBehavior = FillBehavior.Stop,\n                AutoReverse = true\n            };\n\n            MainCamera.BeginAnimation( ProjectionCamera.PositionProperty, animationCamera );\n        }\n    }\n}"
  },
  {
    "path": "Plugins.sln/Cube3D/MainWindow.frame.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of Cube3D.\n\nCube3D is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nCube3D is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with Cube3D. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System.Linq;\nusing System.Threading.Tasks;\nusing ScreenCapture;\n\nnamespace Cube3D\n{\n    public partial class MainWindow\n    {\n        private D3D9ShareCapture _capture;\n        private FrameToD3DImage  _frameProcessor;\n\n        private Task StartPrimaryMonitorCapture()\n        {\n            var monitor = ( from m in MonitorEnumerationHelper.GetMonitors()\n                where m.IsPrimary\n                select m ).First();\n            return StartMonitorCapture( monitor );\n        }\n\n        private async Task StartMonitorCapture( MonitorInfo mi )\n        {\n            _frameProcessor = new FrameToD3DImage( D3DImages.D3DImages.D3DImageDict );\n            try\n            {\n                _capture = D3D9ShareCapture.Create( mi, _frameProcessor );\n            }\n            catch\n            {\n                await Task.Delay( 1000 );\n                App.Restart();\n                return;\n            }\n\n            if ( _capture != null )\n            {\n                _capture.StartCaptureSession();\n#if DEBUG\n                await Task.Delay( 50 );\n#endif\n            }\n\n            StopCapture();\n        }\n    }\n}"
  },
  {
    "path": "Plugins.sln/Cube3D/MainWindow.hotkeys.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of Cube3D.\n\nCube3D is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nCube3D is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with Cube3D. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Text;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing System.Windows;\nusing Cube3D.Config;\nusing Cube3D.Effects;\nusing ScreenCapture;\nusing VirtualSpace.Commons;\nusing VirtualSpace.Helpers;\nusing VirtualSpace.Plugin;\n\n#pragma warning disable CA1416\n\nnamespace Cube3D\n{\n    public partial class MainWindow\n    {\n        private static   SettingsWindow _sw;\n        private readonly StringBuilder  _sbWinInfo = new( 1024 );\n        private          bool           _isTopmost;\n\n        private void FakeHide( bool stopCapture = false )\n        {\n            Left = Const.FakeHideX;\n            Top = Const.FakeHideY;\n\n            if ( stopCapture ) StopCapture();\n        }\n\n        private void StopCapture()\n        {\n            _capture?.StopCaptureSession();\n        }\n\n        private bool WindowFilter( IntPtr hWnd, int lParam )\n        {\n            if ( !User32.IsWindowVisible( hWnd ) )\n                return true;\n\n            _sbWinInfo.Clear();\n            _ = User32.GetWindowText( hWnd, _sbWinInfo, _sbWinInfo.Capacity );\n            if ( _sbWinInfo.Length == 0 )\n                return true;\n\n            _isTopmost = Handle == hWnd; // if the first visible non-empty title window is Cube3D, then Cube3D is on the top.\n\n            return false;\n        }\n\n        private void RealShow( bool forceTop = false )\n        {\n            if ( forceTop )\n            {\n                _ = User32.EnumWindows( WindowFilter, 0 );\n                if ( !_isTopmost )\n                {\n                    User32.SetWindowPos( Handle, User32.SpecialWindowHandles.HWND_TOP, 0, 0, 0, 0,\n                        User32.SetWindowPosFlags.SWP_NOSIZE |\n                        User32.SetWindowPosFlags.SWP_NOMOVE |\n                        User32.SetWindowPosFlags.SWP_NOACTIVATE |\n                        User32.SetWindowPosFlags.SWP_NOREDRAW |\n                        User32.SetWindowPosFlags.SWP_NOCOPYBITS |\n                        User32.SetWindowPosFlags.SWP_DEFERERASE |\n                        User32.SetWindowPosFlags.SWP_NOSENDCHANGING\n                    );\n                }\n            }\n\n            var dpi = GetDpiForMonitor( _monitorInfo.Hmon );\n\n            Left = _monitorInfo.WorkArea.Left / dpi.ScaleX;\n            Top = _monitorInfo.WorkArea.Top / dpi.ScaleY;\n            Width = _monitorInfo.ScreenSize.X / dpi.ScaleX;\n            Height = _monitorInfo.ScreenSize.Y / dpi.ScaleY;\n        }\n\n        private IntPtr WndProc( IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled )\n        {\n            switch ( msg )\n            {\n                case WinMsg.WM_SYSCOMMAND:\n                    var wP = wParam.ToInt32();\n                    if ( wP is WinMsg.SC_RESTORE or WinMsg.SC_MINIMIZE or WinMsg.SC_MAXIMIZE )\n                        handled = true;\n                    break;\n\n                case WinApi.WM_COPYDATA:\n                    var copyDataStruct = (COPYDATASTRUCT)Marshal.PtrToStructure( lParam, typeof( COPYDATASTRUCT ) );\n                    switch ( copyDataStruct.dwData.ToInt32() )\n                    {\n                        case WinApi.UM_SWITCHDESKTOP:\n                            if ( _mainWindowRunningAnimationCount == 0 )\n                            {\n                                var vdSwitchInfo =\n                                    (VirtualDesktopSwitchInfo)Marshal.PtrToStructure( copyDataStruct.lpData, typeof( VirtualDesktopSwitchInfo ) );\n\n                                Task.Run( () => { Dispatcher.Invoke( () => PerformAnimationPrimary( vdSwitchInfo ) ); } );\n                                foreach ( var other in OtherScreens )\n                                {\n                                    other.PerformAnimationOthers( vdSwitchInfo );\n                                }\n                            }\n\n                            break;\n                    }\n\n                    break;\n\n                case WinApi.UM_PLUGINSETTINGS:\n                    if ( _sw is null || PresentationSource.FromVisual( _sw ) == null )\n                    {\n                        _sw = new SettingsWindow();\n                        _sw.SetMainWindow( this );\n                        _sw.ShowDialog();\n                    }\n                    else\n                    {\n                        _sw.Activate();\n                    }\n\n                    break;\n                case WinApi.UM_OTHERSCREENS:\n                    switch ( wParam.ToInt32() )\n                    {\n                        case 0:\n                            ClearOtherScreens();\n                            break;\n                        case 1:\n                            CreateOtherScreens();\n                            break;\n                    }\n\n                    break;\n\n                case WinMsg.WM_DISPLAYCHANGE:\n                    App.Restart();\n                    break;\n                case WinApi.UM_RESTART:\n                    App.Restart();\n                    break;\n\n                case WinMsg.WM_MOUSEACTIVATE:\n                    handled = true;\n                    return new IntPtr( WinMsg.MA_NOACTIVATE );\n            }\n\n            return IntPtr.Zero;\n        }\n\n        private void PerformAnimationPrimary( VirtualDesktopSwitchInfo vdSwitchInfo )\n        {\n            var mi = ( from m in MonitorEnumerationHelper.GetMonitors() where m.IsPrimary select m ).First();\n            _capture = D3D9ShareCapture.Create( mi, _frameProcessor );\n            _capture?.StartCaptureSession();\n\n            if ( ( SettingsManager.Settings.TransitionType & TransitionType.NotificationGridOnly ) > 0 )\n                NotificationGridLayout( vdSwitchInfo.vdCount );\n\n            var em = EaseFactory.GetEaseModeByName( SettingsManager.Settings.EaseMode );\n            var ef = EaseFactory.GetEaseByName( SettingsManager.Settings.EaseType, em );\n\n            _frameProcessor.SetAction( () =>\n            {\n                //////////////////////////////////////////////////////\n                // trigger action only after first frame be handled,\n                // see FrameToD3DImage.Proceed() for detail.\n                RealShow( true );\n\n                if ( ( SettingsManager.Settings.TransitionType & TransitionType.NotificationGridOnly ) > 0 )\n                {\n                    NotificationGridAnimation( vdSwitchInfo.fromIndex, vdSwitchInfo.targetIndex, vdSwitchInfo.vdCount, ef );\n                    Interlocked.Increment( ref _mainWindowRunningAnimationCount );\n                }\n\n                if ( vdSwitchInfo.targetIndex != vdSwitchInfo.fromIndex &&\n                     ( SettingsManager.Settings.TransitionType & TransitionType.AnimationOnly ) > 0 )\n                {\n                    _effect.AnimationInDirection( (KeyCode)vdSwitchInfo.dir, MainModel3DGroup, ef );\n                    Interlocked.Increment( ref _mainWindowRunningAnimationCount );\n                }\n\n                WinApi.PostMessage( vdSwitchInfo.hostHandle, WinApi.UM_SWITCHDESKTOP, (uint)vdSwitchInfo.targetIndex, 0 );\n            } );\n        }\n\n        private void PerformAnimationOthers( VirtualDesktopSwitchInfo vdSwitchInfo )\n        {\n            if ( ( SettingsManager.Settings.TransitionType & TransitionType.NotificationGridOnly ) == 0 ) return;\n\n            NotificationGridLayout( vdSwitchInfo.vdCount );\n\n            var em = EaseFactory.GetEaseModeByName( SettingsManager.Settings.EaseMode );\n            var ef = EaseFactory.GetEaseByName( SettingsManager.Settings.EaseType, em );\n\n            RealShow();\n\n            NotificationGridAnimation( vdSwitchInfo.fromIndex, vdSwitchInfo.targetIndex, vdSwitchInfo.vdCount, ef );\n        }\n    }\n}\n\n#pragma warning restore CA1416"
  },
  {
    "path": "Plugins.sln/Cube3D/MainWindow.xaml",
    "content": "﻿<Window x:Class=\"Cube3D.MainWindow\"\n        xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n        xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n        xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n        xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n        mc:Ignorable=\"d\"\n        Title=\"Cube3D For VirtualSpace\" Left=\"0\" Top=\"0\" Height=\"1440\" Width=\"2560\"\n        WindowStyle=\"None\" ResizeMode=\"NoResize\"\n        Loaded=\"Window_Loaded\" ShowInTaskbar=\"False\">\n    <Window.Resources>\n        <ResourceDictionary>\n            <Thickness x:Key=\"NotifyButtonMargin\"></Thickness>\n            <ControlTemplate x:Key=\"NotifyButtonTemplate\" TargetType=\"Button\">\n                <Border BorderThickness=\"0\" CornerRadius=\"5\" Background=\"#C4C4C4\"\n                        Margin=\"{DynamicResource NotifyButtonMargin}\">\n                    <ContentPresenter HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" />\n                </Border>\n            </ControlTemplate>\n            <ControlTemplate x:Key=\"NotifyButtonTemplateCurrent\" TargetType=\"Button\">\n                <Border BorderThickness=\"0\" CornerRadius=\"5\" Background=\"White\"\n                        Margin=\"{DynamicResource NotifyButtonMargin}\">\n                    <ContentPresenter HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" />\n                </Border>\n            </ControlTemplate>\n        </ResourceDictionary>\n    </Window.Resources>\n\n    <WindowChrome.WindowChrome>\n        <WindowChrome x:Name=\"WinChrome\" CaptionHeight=\"0\" />\n    </WindowChrome.WindowChrome>\n\n    <Grid>\n        <Viewport3D x:Name=\"Vp3D\" ClipToBounds=\"False\" IsHitTestVisible=\"False\"\n                    RenderOptions.EdgeMode=\"Aliased\" RenderOptions.CachingHint=\"Cache\">\n            <Viewport3D.Camera>\n                <PerspectiveCamera x:Name=\"MainCamera\" Position=\"0,0,10\" LookDirection=\"0,0,-1\" />\n            </Viewport3D.Camera>\n            <ModelVisual3D x:Name=\"Mv3D\">\n                <ModelVisual3D.Content>\n                    <Model3DGroup x:Name=\"MainModel3DGroup\" />\n                </ModelVisual3D.Content>\n            </ModelVisual3D>\n            <!--\n            <Viewport2DVisual3D x:Name=\"Vp2Dv3D\">\n                <Viewport2DVisual3D.Geometry>\n                    <MeshGeometry3D TriangleIndices=\"0 1 2 2 3 0\" TextureCoordinates=\"0,1 1,1 1,0 0,0\" />\n                </Viewport2DVisual3D.Geometry>\n                <Viewport2DVisual3D.Material>\n                    <DiffuseMaterial Viewport2DVisual3D.IsVisualHostMaterial=\"True\" Brush=\"Gray\" />\n                </Viewport2DVisual3D.Material>\n            </Viewport2DVisual3D>\n            -->\n        </Viewport3D>\n        <Grid x:Name=\"NotifyContainer\" Visibility=\"Hidden\" Width=\"0\" Height=\"0\">\n            <Border x:Name=\"NotifyBorder\" Background=\"#6C6C6C\" CornerRadius=\"10\">\n                <UniformGrid x:Name=\"NotifyGrid\" />\n            </Border>\n            <Button x:Name=\"CurrentIndicator\" Template=\"{StaticResource NotifyButtonTemplateCurrent}\" />\n        </Grid>\n    </Grid>\n</Window>"
  },
  {
    "path": "Plugins.sln/Cube3D/MainWindow.xaml.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of Cube3D.\n\nCube3D is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nCube3D is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with Cube3D. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Windows;\nusing System.Windows.Interop;\nusing System.Windows.Media;\nusing Cube3D.Config;\nusing ScreenCapture;\nusing VirtualSpace.Commons;\nusing VirtualSpace.Helpers;\nusing VirtualSpace.Plugin;\n\n#pragma warning disable CA1416\n\nnamespace Cube3D\n{\n    /// <summary>\n    ///     Interaction logic for MainWindow.xaml\n    /// </summary>\n    public partial class MainWindow : Window\n    {\n        private static readonly List<MainWindow> OtherScreens = new();\n\n        private readonly MonitorInfo _monitorInfo;\n        public           IntPtr      Handle;\n\n        public MainWindow()\n        {\n            InitializeComponent();\n\n            _monitorInfo = ( from m in MonitorEnumerationHelper.GetMonitors() where m.IsPrimary select m ).First();\n\n            var dpi = GetDpiForMonitor( _monitorInfo.Hmon );\n            Left = 0;\n            Top = 0;\n            Width = _monitorInfo.ScreenSize.X / dpi.ScaleX;\n            Height = _monitorInfo.ScreenSize.Y / dpi.ScaleY;\n\n            Topmost = true;\n            ShowActivated = false;\n\n            new WindowInteropHelper( this ).EnsureHandle();\n        }\n\n        private MainWindow( MonitorInfo mi )\n        {\n            InitializeComponent();\n\n            _monitorInfo = mi;\n\n            var dpi = GetDpiForMonitor( _monitorInfo.Hmon );\n            Left = _monitorInfo.WorkArea.Left / dpi.ScaleX;\n            Top = _monitorInfo.WorkArea.Top / dpi.ScaleY;\n            Width = _monitorInfo.ScreenSize.X / dpi.ScaleX;\n            Height = _monitorInfo.ScreenSize.Y / dpi.ScaleY;\n\n            Topmost = true;\n            ShowActivated = false;\n\n            new WindowInteropHelper( this ).EnsureHandle();\n        }\n\n        private static (double ScaleX, double ScaleY) GetDpiForMonitor( IntPtr hMon )\n        {\n            _ = User32.GetDpiForMonitor( hMon, User32.MonitorDpiType.MDT_EFFECTIVE_DPI, out var dpiX, out var dpiY );\n            return new ValueTuple<double, double>( dpiX / 96.0, dpiY / 96.0 );\n        }\n\n        protected override void OnSourceInitialized( EventArgs e )\n        {\n            base.OnSourceInitialized( e );\n            Handle = new WindowInteropHelper( this ).EnsureHandle();\n            var source = HwndSource.FromHwnd( Handle );\n            source?.AddHook( WndProc );\n        }\n\n        private void Register()\n        {\n            if ( !_monitorInfo.IsPrimary ) return;\n\n            var pipeMessage = new PipeMessage\n            {\n                Type = PipeMessageType.PLUGIN_VD_SWITCH_OBSERVER,\n                Name = PluginManager.PluginInfo.Name,\n                Handle = Handle.ToInt32()\n            };\n\n            void Exit()\n            {\n                Application.Current.Shutdown();\n            }\n\n            void SetOwner( HostInfo hostInfo )\n            {\n                var pluginInfo = PluginManager.PluginInfo;\n                if ( pluginInfo.Requirements.HostVersion == null ||\n                     pluginInfo.Requirements.HostVersion > hostInfo.Version )\n                {\n                    MessageBox.Show( \"Plugin Error.\\nThe host does not meet the Requirements.\" );\n                    Exit();\n                    return;\n                }\n\n                User32.SetWindowLongPtr( new HandleRef( this, Handle ),\n                    (int)GetWindowLongFields.GWL_HWNDPARENT,\n                    hostInfo.MainWindowHandle\n                );\n            }\n\n            IpcPipeClient.PluginCheckIn<HostInfo>(\n                pipeMessage,\n                () => { MessageBox.Show( \"This Program require VirtualSpace running first.\" ); },\n                Exit,\n                SetOwner\n            );\n#if DEBUG\n            var interval = 1;\n#else\n            var interval = SettingsManager.Settings.CheckAliveInterval;\n#endif\n            IpcPipeClient.CheckAlive( pipeMessage.Name, pipeMessage.Handle, pipeMessage.ProcessId, interval, Exit );\n        }\n\n        private void Bootstrap()\n        {\n            Register();\n\n            FixStyle();\n\n            CameraPosition( _monitorInfo );\n\n            _animationNotifyGrid.Completed += AnimationCompleted;\n        }\n\n        private void FixStyle()\n        {\n            _ = User32.SetWindowDisplayAffinity( Handle, User32.WDA_EXCLUDEFROMCAPTURE ); // self exclude from screen capture\n\n            var style = User32.GetWindowLong( Handle, (int)GetWindowLongFields.GWL_STYLE );\n            style = unchecked(style | (int)0x80000000); // WS_POPUP\n            User32.SetWindowLongPtr( new HandleRef( this, Handle ), (int)GetWindowLongFields.GWL_STYLE, style );\n\n            var exStyle = User32.GetWindowLong( Handle, (int)GetWindowLongFields.GWL_EXSTYLE );\n            exStyle |= 0x08000000; // WS_EX_NOACTIVATE\n            exStyle &= ~0x00040000; // WS_EX_APPWINDOW\n            User32.SetWindowLongPtr( new HandleRef( this, Handle ), (int)GetWindowLongFields.GWL_EXSTYLE, exStyle );\n        }\n\n        private async void Window_Loaded( object sender, RoutedEventArgs e )\n        {\n            FakeHide();\n\n            SetTransitionType();\n\n            Bootstrap();\n\n            if ( _monitorInfo.IsPrimary )\n            {\n                Build3D();\n\n                await StartPrimaryMonitorCapture();\n\n                CreateOtherScreens();\n            }\n        }\n\n        public void SetTransitionType()\n        {\n            if ( SettingsManager.Settings.TransitionType == TransitionType.NotificationGridOnly || !_monitorInfo.IsPrimary )\n            {\n                Background = (Brush)Application.Current.Resources[\"BackgroundTrans\"];\n                WinChrome.GlassFrameThickness = new Thickness( -1 );\n                Vp3D.Visibility = Visibility.Hidden;\n            }\n            else\n            {\n                Background = (Brush)Application.Current.Resources[\"BackgroundLgb\"];\n                WinChrome.GlassFrameThickness = new Thickness( 0 );\n                Vp3D.Visibility = Visibility.Visible;\n            }\n\n            NotifyContainer.Visibility = ( SettingsManager.Settings.TransitionType & TransitionType.NotificationGridOnly ) > 0 || !_monitorInfo.IsPrimary\n                ? Visibility.Visible\n                : Visibility.Hidden;\n        }\n\n        private void CreateOtherScreens()\n        {\n            if ( ( SettingsManager.Settings.TransitionType & TransitionType.NotificationGridOnly ) == 0 ||\n                 !SettingsManager.Settings.ShowNotificationGridOnAllScreens ) return;\n\n            ClearOtherScreens();\n            var others = ( from m in MonitorEnumerationHelper.GetMonitors()\n                where !m.IsPrimary\n                select m ).ToList();\n            foreach ( var ow in from mi in others select new MainWindow( mi ) )\n            {\n                OtherScreens.Add( ow );\n                User32.SetWindowLongPtr( new HandleRef( ow, ow.Handle ),\n                    (int)GetWindowLongFields.GWL_HWNDPARENT,\n                    Handle.ToInt32()\n                );\n                ow.Show();\n            }\n        }\n\n        private static void ClearOtherScreens()\n        {\n            foreach ( var ow in OtherScreens )\n            {\n                ow.Close();\n            }\n\n            OtherScreens.Clear();\n        }\n    }\n}\n\n#pragma warning restore CA1416"
  },
  {
    "path": "Plugins.sln/Cube3D/SettingsWindow.xaml",
    "content": "﻿<Window x:Class=\"Cube3D.SettingsWindow\"\n        xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n        xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n        xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n        xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n        xmlns:cvt=\"clr-namespace:VirtualSpace.Helpers\"\n        mc:Ignorable=\"d\"\n        xmlns:localConfig=\"clr-namespace:Cube3D.Config\"\n        Title=\"Cube3D Settings\" Height=\"450\" Width=\"800\" Topmost=\"True\" Loaded=\"Window_Loaded\" WindowStartupLocation=\"CenterScreen\">\n    <Window.Resources>\n        <cvt:TransitionTypeConverter x:Key=\"Ttc\" />\n    </Window.Resources>\n    <Grid>\n        <StackPanel>\n            <StackPanel>\n                <GroupBox Header=\"Basic\" Margin=\"10\">\n                    <StackPanel>\n                        <StackPanel Orientation=\"Horizontal\">\n                            <Label Margin=\"10,10,0,0\" Width=\"180\">Animation Duration(ms):</Label>\n                            <Slider x:Name=\"SliderAnimationDuration\" Margin=\"10,15,0,0\" HorizontalAlignment=\"Left\" Width=\"300\"\n                                    IsSnapToTickEnabled=\"True\" IsMoveToPointEnabled=\"True\"\n                                    Minimum=\"{Binding Source={x:Static localConfig:Const.AnimationDurationMin}}\"\n                                    Maximum=\"{Binding Source={x:Static localConfig:Const.AnimationDurationMax}}\"\n                                    Value=\"{Binding AnimationDuration}\" TickFrequency=\"10\" TickPlacement=\"None\" LargeChange=\"10\" />\n                            <TextBlock Margin=\"5,16,0,0\" Text=\"{Binding ElementName=SliderAnimationDuration, Path=Value}\" />\n                        </StackPanel>\n                        <StackPanel Orientation=\"Horizontal\">\n                            <Label Margin=\"10,10,0,0\" Width=\"180\">Animation Type:</Label>\n                            <ComboBox Width=\"120\" Margin=\"10,10,0,0\" x:Name=\"ComboBoxEffects\" SelectionChanged=\"ComboBoxEffects_SelectionChanged\" />\n                            <Button Width=\"120\" Margin=\"10, 10,0,0\" Click=\"ApplyEffect_OnClick\">Apply</Button>\n                        </StackPanel>\n                        <StackPanel Orientation=\"Horizontal\">\n                            <Label Margin=\"10,10,0,0\" Width=\"180\" xml:space=\"preserve\">        Ease Type:</Label>\n                            <ComboBox Width=\"120\" Margin=\"10,10,0,0\" x:Name=\"ComboBoxEase\" SelectionChanged=\"ComboBoxEase_OnSelectionChanged\" />\n                        </StackPanel>\n                        <StackPanel Orientation=\"Horizontal\">\n                            <Label Margin=\"10,10,0,0\" Width=\"180\" xml:space=\"preserve\">        Ease Mode:</Label>\n                            <ComboBox Width=\"120\" Margin=\"10,10,0,0\" x:Name=\"ComboBoxEaseMode\" SelectionChanged=\"ComboBoxEaseMode_OnSelectionChanged\" />\n                        </StackPanel>\n                        <StackPanel Orientation=\"Horizontal\">\n                            <Label Margin=\"10,10,0,0\" Width=\"180\">Transition Type:</Label>\n                            <ComboBox Width=\"300\" Margin=\"10,10,0,0\" x:Name=\"ComboBoxTransitionType\" SelectionChanged=\"ComboBoxTransitionType_OnSelectionChanged\" />\n                            <CheckBox Margin=\"10,15,0,0\" x:Name=\"CbNgOnAllScreens\" Checked=\"CbNgOnAllScreens_OnChecked\" Unchecked=\"CbNgOnAllScreens_OnUnchecked\"\n                                      IsEnabled=\"{Binding ElementName=ComboBoxTransitionType,\n                                      Path=SelectedItem,\n                                      Converter={StaticResource Ttc} }\">\n                                Show NotificationGrid on All Screens\n                            </CheckBox>\n                        </StackPanel>\n                    </StackPanel>\n                </GroupBox>\n                <GroupBox Header=\"Others\" Margin=\"10\">\n                    <StackPanel>\n                        <StackPanel Orientation=\"Horizontal\">\n                            <Label Margin=\"10,10,0,0\" Width=\"180\">Check Alive Interval(seconds):</Label>\n                            <Slider x:Name=\"SliderCheckAliveInterval\" Margin=\"10,15,0,0\" HorizontalAlignment=\"Left\" Width=\"300\"\n                                    IsSnapToTickEnabled=\"True\" IsMoveToPointEnabled=\"True\"\n                                    Minimum=\"{Binding Source={x:Static localConfig:Const.CheckAliveIntervalMin}}\"\n                                    Maximum=\"{Binding Source={x:Static localConfig:Const.CheckAliveIntervalMax}}\"\n                                    Value=\"{Binding CheckAliveInterval}\" TickPlacement=\"None\" />\n                            <TextBlock Margin=\"5,16,0,0\" Text=\"{Binding ElementName=SliderCheckAliveInterval, Path=Value}\" />\n                        </StackPanel>\n                    </StackPanel>\n                </GroupBox>\n            </StackPanel>\n            <StackPanel Orientation=\"Horizontal\" HorizontalAlignment=\"Right\" Margin=\"10\">\n                <Button Padding=\"5\" Click=\"Close_OnClick\">Close</Button>\n            </StackPanel>\n        </StackPanel>\n    </Grid>\n</Window>"
  },
  {
    "path": "Plugins.sln/Cube3D/SettingsWindow.xaml.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of Cube3D.\n// \n// Cube3D is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// Cube3D is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with Cube3D. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Windows;\nusing System.Windows.Controls;\nusing Cube3D.Config;\nusing Cube3D.Effects;\nusing VirtualSpace.Plugin;\n\nnamespace Cube3D\n{\n    public partial class SettingsWindow : Window\n    {\n        private bool       _isLoaded = false;\n        private MainWindow _mainWindow;\n\n        public SettingsWindow()\n        {\n            DataContext = this;\n            InitializeComponent();\n        }\n\n        public int AnimationDuration\n        {\n            get => SettingsManager.Settings.AnimationDuration;\n            set => SettingsManager.Settings.AnimationDuration = value;\n        }\n\n        public int CheckAliveInterval\n        {\n            get => SettingsManager.Settings.CheckAliveInterval;\n            set => SettingsManager.Settings.CheckAliveInterval = value;\n        }\n\n        private void Window_Loaded( object sender, RoutedEventArgs e )\n        {\n            foreach ( EffectType effect in Enum.GetValues( typeof( EffectType ) ) )\n            {\n                ComboBoxEffects.Items.Add( effect );\n            }\n\n            ComboBoxEffects.SelectedItem = SettingsManager.Settings.SelectedEffect;\n\n            foreach ( EaseType ease in Enum.GetValues( typeof( EaseType ) ) )\n            {\n                ComboBoxEase.Items.Add( ease );\n            }\n\n            ComboBoxEase.SelectedItem = SettingsManager.Settings.EaseType;\n\n            foreach ( EaseMode easeMode in Enum.GetValues( typeof( EaseMode ) ) )\n            {\n                ComboBoxEaseMode.Items.Add( easeMode );\n            }\n\n            ComboBoxEaseMode.SelectedItem = SettingsManager.Settings.EaseMode;\n\n            foreach ( TransitionType tt in Enum.GetValues( typeof( TransitionType ) ) )\n            {\n                ComboBoxTransitionType.Items.Add( tt );\n            }\n\n            ComboBoxTransitionType.SelectedItem = SettingsManager.Settings.TransitionType;\n\n            CbNgOnAllScreens.IsChecked = SettingsManager.Settings.ShowNotificationGridOnAllScreens;\n\n            _isLoaded = true;\n        }\n\n        private void ComboBoxEffects_SelectionChanged( object sender, SelectionChangedEventArgs e )\n        {\n            if ( !_isLoaded ) return;\n            SettingsManager.Settings.SelectedEffect = (EffectType)ComboBoxEffects.SelectedItem;\n            SettingsManager.SaveJson();\n        }\n\n        private void ComboBoxEase_OnSelectionChanged( object sender, SelectionChangedEventArgs e )\n        {\n            if ( !_isLoaded ) return;\n            SettingsManager.Settings.EaseType = (EaseType)ComboBoxEase.SelectedItem;\n            SettingsManager.SaveJson();\n        }\n\n        private void ComboBoxEaseMode_OnSelectionChanged( object sender, SelectionChangedEventArgs e )\n        {\n            if ( !_isLoaded ) return;\n            SettingsManager.Settings.EaseMode = (EaseMode)ComboBoxEaseMode.SelectedItem;\n            SettingsManager.SaveJson();\n        }\n\n        private void ComboBoxTransitionType_OnSelectionChanged( object sender, SelectionChangedEventArgs e )\n        {\n            if ( !_isLoaded ) return;\n            SettingsManager.Settings.TransitionType = (TransitionType)ComboBoxTransitionType.SelectedItem;\n            if ( ( SettingsManager.Settings.TransitionType & TransitionType.NotificationGridOnly ) == 0 )\n                CbNgOnAllScreens.IsChecked = false;\n            SettingsManager.SaveJson();\n            _mainWindow.SetTransitionType();\n        }\n\n        public void SetMainWindow( MainWindow mw )\n        {\n            _mainWindow = mw;\n        }\n\n        private void ApplyEffect_OnClick( object sender, RoutedEventArgs e )\n        {\n            _mainWindow.Build3D();\n        }\n\n        private void Close_OnClick( object sender, RoutedEventArgs e )\n        {\n            SettingsManager.SaveJson();\n            Close();\n        }\n\n        private void CbNgOnAllScreens_OnChecked( object sender, RoutedEventArgs e )\n        {\n            if ( !_isLoaded ) return;\n            SettingsManager.Settings.ShowNotificationGridOnAllScreens = true;\n            SettingsManager.SaveJson();\n            WinApi.PostMessage( _mainWindow.Handle, WinApi.UM_OTHERSCREENS, 1, 0 );\n        }\n\n        private void CbNgOnAllScreens_OnUnchecked( object sender, RoutedEventArgs e )\n        {\n            if ( !_isLoaded ) return;\n            SettingsManager.Settings.ShowNotificationGridOnAllScreens = false;\n            SettingsManager.SaveJson();\n            WinApi.PostMessage( _mainWindow.Handle, WinApi.UM_OTHERSCREENS, 0, 0 );\n        }\n    }\n}"
  },
  {
    "path": "Plugins.sln/Cube3D/app.manifest",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<assembly manifestVersion=\"1.0\" xmlns=\"urn:schemas-microsoft-com:asm.v1\" xmlns:asmv3=\"urn:schemas-microsoft-com:asm.v3\">\n    <assemblyIdentity version=\"1.0.0.0\" name=\"VirtualSpace\"/>\n    <trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v2\">\n        <security>\n            <requestedPrivileges xmlns=\"urn:schemas-microsoft-com:asm.v3\">\n                <!-- UAC 清单选项\n                     如果想要更改 Windows 用户帐户控制级别，请使用\n                     以下节点之一替换 requestedExecutionLevel 节点。n\n                <requestedExecutionLevel  level=\"asInvoker\" uiAccess=\"false\" />\n                <requestedExecutionLevel  level=\"requireAdministrator\" uiAccess=\"false\" />\n                <requestedExecutionLevel  level=\"highestAvailable\" uiAccess=\"false\" />\n        \n                    指定 requestedExecutionLevel 元素将禁用文件和注册表虚拟化。\n                    如果你的应用程序需要此虚拟化来实现向后兼容性，则删除此\n                    元素。\n                -->\n                <requestedExecutionLevel level=\"asInvoker\" uiAccess=\"false\"/>\n            </requestedPrivileges>\n        </security>\n    </trustInfo>\n\n    <compatibility xmlns=\"urn:schemas-microsoft-com:compatibility.v1\">\n        <application>\n            <!-- 设计此应用程序与其一起工作且已针对此应用程序进行测试的\n                 Windows 版本的列表。取消评论适当的元素，\n                 Windows 将自动选择最兼容的环境。 -->\n\n            <!-- Windows Vista -->\n            <!--<supportedOS Id=\"{e2011457-1546-43c5-a5fe-008deee3d3f0}\" />-->\n\n            <!-- Windows 7 -->\n            <!--<supportedOS Id=\"{35138b9a-5d96-4fbd-8e2d-a2440225f93a}\" />-->\n\n            <!-- Windows 8 -->\n            <!--<supportedOS Id=\"{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}\" />-->\n\n            <!-- Windows 8.1 -->\n            <!--<supportedOS Id=\"{1f676c76-80e1-4239-95bb-83d0f6d0da78}\" />-->\n\n            <!-- Windows 10 -->\n            <supportedOS Id=\"{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}\"/>\n\n        </application>\n    </compatibility>\n\n    <!-- 指示该应用程序可感知 DPI 且 Windows 在 DPI 较高时将不会对其进行\n         自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI，无需\n         选择加入。选择加入此设置的 Windows 窗体应用程序(面向 .NET Framework 4.6)还应\n         在其 app.config 中将 \"EnableWindowsFormsHighDpiAutoResizing\" 设置设置为 \"true\"。\n         \n         将应用程序设为感知长路径。请参阅 https://docs.microsoft.com/windows/win32/fileio/maximum-file-path-limitation -->\n    <!--\n    <application xmlns=\"urn:schemas-microsoft-com:asm.v3\">\n      <windowsSettings>\n        <dpiAware xmlns=\"http://schemas.microsoft.com/SMI/2005/WindowsSettings\">true</dpiAware>\n        <longPathAware xmlns=\"http://schemas.microsoft.com/SMI/2016/WindowsSettings\">true</longPathAware>\n      </windowsSettings>\n    </application>\n    -->\n\n    <asmv3:application>\n        <asmv3:windowsSettings>\n            <dpiAwareness xmlns=\"http://schemas.microsoft.com/SMI/2016/WindowsSettings\">PerMonitorV2</dpiAwareness>\n        </asmv3:windowsSettings>\n    </asmv3:application>\n\n    <!-- 启用 Windows 公共控件和对话框的主题(Windows XP 和更高版本) -->\n    <!--\n    <dependency>\n      <dependentAssembly>\n        <assemblyIdentity\n            type=\"win32\"\n            name=\"Microsoft.Windows.Common-Controls\"\n            version=\"6.0.0.0\"\n            processorArchitecture=\"*\"\n            publicKeyToken=\"6595b64144ccf1df\"\n            language=\"*\"\n          />\n      </dependentAssembly>\n    </dependency>\n    -->\n\n</assembly>\n"
  },
  {
    "path": "Plugins.sln/Cube3D/plugin.json",
    "content": "{\n  \"Name\": \"Cube3D\",\n  \"Display\": \"Cube3D\",\n  \"Version\": \"2.1\",\n  \"Author\": \"Dylan Cheng\",\n  \"Email\": \"newlooper@hotmail.com\",\n  \"Entry\": \"Cube3D.exe\",\n  \"AutoStart\": true,\n  \"AutoStartTiming\": 1,\n  \"RestartPolicy\": {\n    \"Trigger\": 0,\n    \"Values\": [\n      \"HotplugDetected\"\n    ],\n    \"Enabled\": false\n  },\n  \"ClosePolicy\": {\n    \"Trigger\": 0,\n    \"Values\": [\n      \"DIRECTINPUT_NOTIFICATION_MSGSTRING\"\n    ],\n    \"Enabled\": false\n  },\n  \"Requirements\": {\n    \"WinVer\": {\n      \"Min\": {\n        \"Major\": 10,\n        \"Build\": 19041\n      }\n    },\n    \"HostVersion\": \"0.1.454\"\n  }\n}"
  },
  {
    "path": "Plugins.sln/Cube3D/settings.json",
    "content": "{\n  \"AnimationDuration\": 500,\n  \"CheckAliveInterval\": 30,\n  \"SelectedEffect\": 0,\n  \"TransitionType\": 3\n}"
  },
  {
    "path": "Plugins.sln/Plugins.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 17\nVisualStudioVersion = 17.1.32210.238\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Cube3D\", \"Cube3D\\Cube3D.csproj\", \"{10B545AA-DE50-4D87-A7F4-804BA41E0035}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"ScreenCapture\", \"ScreenCapture\\ScreenCapture.csproj\", \"{7BDE967F-E467-4775-8BFE-3F63F02499F0}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Plugin\", \"..\\Plugin\\Commons\\Plugin.csproj\", \"{A60FFB45-5547-4CEB-9B41-3D9C58ED9B86}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Ipc\", \"..\\Ipc\\Commons\\Ipc.csproj\", \"{498FD176-AB55-466C-80A5-C11B51C6B8C4}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"IpcClient\", \"..\\Ipc\\IpcClient\\IpcClient.csproj\", \"{EA025C92-FE84-42D7-993E-F94D8CAEFBA9}\"\nEndProject\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"Updater\", \"Updater\\Updater.csproj\", \"{C95060EF-BFD3-4FBB-B8A2-C9A1F5543934}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tRelease|Any CPU = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{10B545AA-DE50-4D87-A7F4-804BA41E0035}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{10B545AA-DE50-4D87-A7F4-804BA41E0035}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{10B545AA-DE50-4D87-A7F4-804BA41E0035}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{10B545AA-DE50-4D87-A7F4-804BA41E0035}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{7BDE967F-E467-4775-8BFE-3F63F02499F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{7BDE967F-E467-4775-8BFE-3F63F02499F0}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{7BDE967F-E467-4775-8BFE-3F63F02499F0}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{7BDE967F-E467-4775-8BFE-3F63F02499F0}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{A60FFB45-5547-4CEB-9B41-3D9C58ED9B86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{A60FFB45-5547-4CEB-9B41-3D9C58ED9B86}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{A60FFB45-5547-4CEB-9B41-3D9C58ED9B86}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{A60FFB45-5547-4CEB-9B41-3D9C58ED9B86}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{498FD176-AB55-466C-80A5-C11B51C6B8C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{498FD176-AB55-466C-80A5-C11B51C6B8C4}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{498FD176-AB55-466C-80A5-C11B51C6B8C4}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{498FD176-AB55-466C-80A5-C11B51C6B8C4}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{EA025C92-FE84-42D7-993E-F94D8CAEFBA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{EA025C92-FE84-42D7-993E-F94D8CAEFBA9}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{EA025C92-FE84-42D7-993E-F94D8CAEFBA9}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{EA025C92-FE84-42D7-993E-F94D8CAEFBA9}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{C95060EF-BFD3-4FBB-B8A2-C9A1F5543934}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{C95060EF-BFD3-4FBB-B8A2-C9A1F5543934}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{C95060EF-BFD3-4FBB-B8A2-C9A1F5543934}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{C95060EF-BFD3-4FBB-B8A2-C9A1F5543934}.Release|Any CPU.Build.0 = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\n\tGlobalSection(ExtensibilityGlobals) = postSolution\n\t\tSolutionGuid = {80A9A318-A8BB-43ED-8290-5E75FC73F82B}\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "Plugins.sln/ScreenCapture/COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "Plugins.sln/ScreenCapture/CaptureHelper.cs",
    "content": "﻿//  ---------------------------------------------------------------------------------\n//  Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n//  The MIT License (MIT)\n// \n//  Permission is hereby granted, free of charge, to any person obtaining a copy\n//  of this software and associated documentation files (the \"Software\"), to deal\n//  in the Software without restriction, including without limitation the rights\n//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n//  copies of the Software, and to permit persons to whom the Software is\n//  furnished to do so, subject to the following conditions:\n// \n//  The above copyright notice and this permission notice shall be included in\n//  all copies or substantial portions of the Software.\n// \n//  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n//  THE SOFTWARE.\n//  ---------------------------------------------------------------------------------\n\n// based on https://github.com/microsoft/Windows.UI.Composition-Win32-Samples/blob/master/dotnet/WPF/ScreenCapture/Composition.WindowsRuntimeHelpers/CaptureHelper.cs\n\nusing System;\nusing System.Runtime.InteropServices;\nusing System.Runtime.InteropServices.WindowsRuntime;\nusing Windows.Graphics.Capture;\n#if NET5_0_OR_GREATER\nusing WinRT;\n#endif\n\nnamespace ScreenCapture\n{\n    public static class CaptureHelper\n    {\n        private static readonly Guid GraphicsCaptureItemGuid = new( \"79C3F95B-31F7-4EC2-A464-632EF5D30760\" );\n\n        public static void SetWindow( this GraphicsCapturePicker picker, IntPtr hwnd )\n        {\n            var interop = (IInitializeWithWindow)(object)picker;\n            interop.Initialize( hwnd );\n        }\n\n        public static GraphicsCaptureItem CreateItemForWindow( IntPtr hwnd )\n        {\n#if NET5_0_OR_GREATER\n            var interop = GraphicsCaptureItem.As<IGraphicsCaptureItemInterop>();\n#else\n            var factory = WindowsRuntimeMarshal.GetActivationFactory( typeof( GraphicsCaptureItem ) );\n            var interop = (IGraphicsCaptureItemInterop)factory;\n#endif\n            var temp        = typeof( GraphicsCaptureItem );\n            var itemPointer = interop.CreateForWindow( hwnd, GraphicsCaptureItemGuid );\n#if NET5_0_OR_GREATER\n            var item = MarshalInterface<GraphicsCaptureItem>.FromAbi( itemPointer );\n#else\n            var item = Marshal.GetObjectForIUnknown( itemPointer ) as GraphicsCaptureItem;\n#endif\n            Marshal.Release( itemPointer );\n\n            return item;\n        }\n\n        public static GraphicsCaptureItem CreateItemForMonitor( IntPtr hmon )\n        {\n#if NET5_0_OR_GREATER\n            var interop = GraphicsCaptureItem.As<IGraphicsCaptureItemInterop>();\n#else\n            var factory = WindowsRuntimeMarshal.GetActivationFactory( typeof( GraphicsCaptureItem ) );\n            var interop = (IGraphicsCaptureItemInterop)factory;\n#endif\n            var temp        = typeof( GraphicsCaptureItem );\n            var itemPointer = interop.CreateForMonitor( hmon, GraphicsCaptureItemGuid );\n\n#if NET5_0_OR_GREATER\n            var item = MarshalInterface<GraphicsCaptureItem>.FromAbi( itemPointer );\n#else\n            var item = Marshal.GetObjectForIUnknown( itemPointer ) as GraphicsCaptureItem;\n#endif\n            Marshal.Release( itemPointer );\n\n            return item;\n        }\n\n        [ComImport]\n        [Guid( \"3E68D4BD-7135-4D10-8018-9FB6D9F33FA1\" )]\n        [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n        [ComVisible( true )]\n        private interface IInitializeWithWindow\n        {\n            void Initialize(\n                IntPtr hwnd );\n        }\n\n        [ComImport]\n        [Guid( \"3628E81B-3CAC-4C60-B7F4-23CE0E0C3356\" )]\n        [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n        [ComVisible( true )]\n        private interface IGraphicsCaptureItemInterop\n        {\n            IntPtr CreateForWindow(\n                [In]     IntPtr window,\n                [In] ref Guid   iid );\n\n            IntPtr CreateForMonitor(\n                [In]     IntPtr monitor,\n                [In] ref Guid   iid );\n        }\n    }\n}"
  },
  {
    "path": "Plugins.sln/ScreenCapture/D3D9ShareCapture.cs",
    "content": "﻿//  ---------------------------------------------------------------------------------\n//  Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n//  The MIT License (MIT)\n// \n//  Permission is hereby granted, free of charge, to any person obtaining a copy\n//  of this software and associated documentation files (the \"Software\"), to deal\n//  in the Software without restriction, including without limitation the rights\n//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n//  copies of the Software, and to permit persons to whom the Software is\n//  furnished to do so, subject to the following conditions:\n// \n//  The above copyright notice and this permission notice shall be included in\n//  all copies or substantial portions of the Software.\n// \n//  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n//  THE SOFTWARE.\n//  ---------------------------------------------------------------------------------\n\n// based on https://github.com/microsoft/Windows.UI.Composition-Win32-Samples/blob/master/dotnet/WPF/ScreenCapture/CaptureSampleCore/BasicCapture.cs \n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\nusing System.Runtime.InteropServices;\nusing Windows.Graphics;\nusing Windows.Graphics.Capture;\nusing Windows.Graphics.DirectX;\nusing Windows.Graphics.DirectX.Direct3D11;\nusing SharpDX.DXGI;\nusing D3D11 = SharpDX.Direct3D11;\nusing D3D9 = SharpDX.Direct3D9;\n\nnamespace ScreenCapture\n{\n    public class D3D9ShareCapture : IDisposable\n    {\n        private static D3D9.Direct3DEx _d3D9Context;\n        private static D3D9.DeviceEx   _d3D9Device;\n        private static IDirect3DDevice _d3D11Device;\n        private static D3D11.Device    _sharpDxD3D11Device;\n        private static PropertyInfo    _propertyInfoIsBorderRequired;\n        private static PropertyInfo    _propertyInfoIsCursorCaptureEnabled;\n\n        private readonly Dictionary<IntPtr, D3D11.Texture2D> _frameCopyPool    = new();\n        private readonly Dictionary<IntPtr, D3D9.Texture>    _renderTargetPool = new();\n        private          Direct3D11CaptureFramePool          _captureFramePool;\n        private          GraphicsCaptureItem                 _captureItem;\n        private          GraphicsCaptureSession              _captureSession;\n        private          FrameProcessor                      _fp;\n        private          ulong                               _frameCount;\n        private          SizeInt32                           _lastSize;\n        private          MonitorInfo                         _monitorInfo;\n\n        private D3D9ShareCapture()\n        {\n            if ( _propertyInfoIsCursorCaptureEnabled != default ) return;\n\n            _d3D9Context = new D3D9.Direct3DEx();\n            _d3D9Device = new D3D9.DeviceEx( _d3D9Context, 0, D3D9.DeviceType.Hardware,\n                IntPtr.Zero, D3D9.CreateFlags.HardwareVertexProcessing | D3D9.CreateFlags.Multithreaded | D3D9.CreateFlags.FpuPreserve,\n                GetPresentParameters() );\n            _d3D11Device = Direct3D11Helper.CreateDevice();\n            _sharpDxD3D11Device = Direct3D11Helper.CreateSharpDXDevice( _d3D11Device );\n\n            var typeGraphicsCaptureSession = typeof( GraphicsCaptureSession );\n            _propertyInfoIsBorderRequired = typeGraphicsCaptureSession.GetProperty( \"IsBorderRequired\" );\n            _propertyInfoIsCursorCaptureEnabled = typeGraphicsCaptureSession.GetProperty( \"IsCursorCaptureEnabled\" );\n        }\n\n        public void Dispose()\n        {\n            _captureFramePool?.Dispose();\n            _captureSession?.Dispose();\n            _captureSession = null;\n            _captureFramePool = null;\n\n            _captureItem = null;\n\n            _fp = null;\n\n            foreach ( var key in _renderTargetPool.Keys )\n            {\n                _renderTargetPool[key].Dispose();\n                _renderTargetPool[key] = null;\n            }\n\n            _renderTargetPool.Clear();\n\n            foreach ( var key in _frameCopyPool.Keys )\n            {\n                _frameCopyPool[key].Dispose();\n                _frameCopyPool[key] = null;\n            }\n\n            _frameCopyPool.Clear();\n        }\n\n        public static D3D9ShareCapture Create( MonitorInfo mi, FrameProcessor fp )\n        {\n            var item = CaptureHelper.CreateItemForMonitor( mi.Hmon );\n            if ( item == null ) return null;\n\n            var capture = new D3D9ShareCapture\n            {\n                _captureItem = item,\n                _fp = fp,\n                _lastSize = item.Size,\n                _monitorInfo = mi\n            };\n\n            return capture;\n        }\n\n        public void UpdateCapturePrimaryMonitor()\n        {\n            var monitor = ( from m in MonitorEnumerationHelper.GetMonitors()\n                where m.IsPrimary\n                select m ).First();\n            if ( monitor.Hmon == _monitorInfo.Hmon ) return;\n            _monitorInfo = monitor;\n\n            var item = CaptureHelper.CreateItemForMonitor( _monitorInfo.Hmon );\n            if ( item != null ) _captureItem = item;\n        }\n\n        public void StartCaptureSession()\n        {\n            if ( _captureItem == null ) return;\n\n            _captureFramePool = Direct3D11CaptureFramePool.Create( _d3D11Device, DirectXPixelFormat.B8G8R8A8UIntNormalized, 1, _captureItem.Size );\n            _captureFramePool.FrameArrived += OnCaptureFrameArrived;\n\n            _captureSession = _captureFramePool.CreateCaptureSession( _captureItem );\n\n            if ( _propertyInfoIsCursorCaptureEnabled != null )\n            {\n                _propertyInfoIsCursorCaptureEnabled.SetValue( _captureSession, false );\n            }\n\n            if ( _propertyInfoIsBorderRequired != null )\n            {\n                try\n                {\n                    _propertyInfoIsBorderRequired.SetValue( _captureSession, false );\n                }\n                catch\n                {\n                    // ignored\n                }\n            }\n\n            _captureSession.StartCapture();\n        }\n\n        public void StopCaptureSession()\n        {\n            Dispose();\n        }\n\n        private void OnCaptureFrameArrived( Direct3D11CaptureFramePool sender, object args )\n        {\n            var newSize = false;\n\n            using ( var frame = sender.TryGetNextFrame() )\n            {\n                if ( frame.ContentSize.Width != _lastSize.Width ||\n                     frame.ContentSize.Height != _lastSize.Height )\n                {\n                    // The thing we have been capturing has changed size.\n                    // We need to resize the swap chain first, then blit the pixels.\n                    // After we do that, retire the frame and then recreate the frame pool.\n                    newSize = true;\n                    _lastSize = frame.ContentSize;\n                }\n\n                using ( var bitmap = Direct3D11Helper.CreateSharpDXTexture2D( frame.Surface ) )\n                {\n                    if ( !_frameCopyPool.ContainsKey( bitmap.NativePointer ) || newSize )\n                    {\n                        var desc = new D3D11.Texture2DDescription\n                        {\n                            BindFlags = D3D11.BindFlags.RenderTarget | D3D11.BindFlags.ShaderResource,\n                            Format = Format.B8G8R8A8_UNorm,\n                            Width = bitmap.Description.Width,\n                            Height = bitmap.Description.Height,\n                            MipLevels = 1,\n                            SampleDescription = new SampleDescription( 1, 0 ),\n                            Usage = D3D11.ResourceUsage.Default,\n                            OptionFlags = D3D11.ResourceOptionFlags.Shared,\n                            CpuAccessFlags = D3D11.CpuAccessFlags.None,\n                            ArraySize = 1\n                        };\n                        _frameCopyPool[bitmap.NativePointer] = new D3D11.Texture2D( _sharpDxD3D11Device, desc );\n                    }\n\n                    var copy = _frameCopyPool[bitmap.NativePointer];\n                    _sharpDxD3D11Device.ImmediateContext.CopyResource( bitmap, copy );\n                    var sharedHandle = GetSharedHandle( copy );\n\n                    if ( !_renderTargetPool.ContainsKey( sharedHandle ) )\n                    {\n                        try\n                        {\n                            _renderTargetPool[sharedHandle] = new D3D9.Texture( _d3D9Device,\n                                copy.Description.Width, copy.Description.Height,\n                                1, D3D9.Usage.RenderTarget,\n                                TranslateFormat( bitmap.Description.Format ),\n                                D3D9.Pool.Default,\n                                ref sharedHandle );\n                        }\n                        catch\n                        {\n                            _d3D9Context = new D3D9.Direct3DEx();\n                            _d3D9Device = new D3D9.DeviceEx( _d3D9Context, 0, D3D9.DeviceType.Hardware,\n                                IntPtr.Zero, D3D9.CreateFlags.HardwareVertexProcessing | D3D9.CreateFlags.Multithreaded | D3D9.CreateFlags.FpuPreserve,\n                                GetPresentParameters() );\n\n                            _renderTargetPool[sharedHandle] = new D3D9.Texture( _d3D9Device,\n                                copy.Description.Width, copy.Description.Height,\n                                1, D3D9.Usage.RenderTarget,\n                                TranslateFormat( bitmap.Description.Format ),\n                                D3D9.Pool.Default,\n                                ref sharedHandle );\n                        }\n                    }\n\n                    using var targetSurface = _renderTargetPool[sharedHandle].GetSurfaceLevel( 0 );\n                    _fp?.Proceed( targetSurface.NativePointer, ++_frameCount );\n                }\n            } // Retire the frame.\n\n            if ( newSize )\n            {\n                _captureFramePool.Recreate(\n                    _d3D11Device,\n                    DirectXPixelFormat.B8G8R8A8UIntNormalized,\n                    1,\n                    _lastSize );\n            }\n        }\n\n        private static D3D9.PresentParameters GetPresentParameters()\n        {\n            var presentParams = new D3D9.PresentParameters\n            {\n                Windowed = true,\n                SwapEffect = D3D9.SwapEffect.Discard,\n                DeviceWindowHandle = NativeMethods.GetDesktopWindow(),\n                PresentationInterval = D3D9.PresentInterval.Default\n            };\n\n            return presentParams;\n        }\n\n        private static IntPtr GetSharedHandle( D3D11.Texture2D texture )\n        {\n            using var resource = texture.QueryInterface<Resource>();\n            return resource.SharedHandle;\n        }\n\n        private static D3D9.Format TranslateFormat( Format format )\n        {\n            return format switch\n            {\n                Format.R10G10B10A2_UNorm => D3D9.Format.A2B10G10R10,\n                Format.R16G16B16A16_Float => D3D9.Format.A16B16G16R16F,\n                Format.B8G8R8A8_UNorm => D3D9.Format.A8R8G8B8,\n                _ => D3D9.Format.Unknown\n            };\n        }\n    }\n\n    public static class NativeMethods\n    {\n        [DllImport( \"user32.dll\", SetLastError = false )]\n        public static extern IntPtr GetDesktopWindow();\n    }\n}"
  },
  {
    "path": "Plugins.sln/ScreenCapture/Direct3D11Helper.cs",
    "content": "﻿//  ---------------------------------------------------------------------------------\n//  Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n//  The MIT License (MIT)\n// \n//  Permission is hereby granted, free of charge, to any person obtaining a copy\n//  of this software and associated documentation files (the \"Software\"), to deal\n//  in the Software without restriction, including without limitation the rights\n//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n//  copies of the Software, and to permit persons to whom the Software is\n//  furnished to do so, subject to the following conditions:\n// \n//  The above copyright notice and this permission notice shall be included in\n//  all copies or substantial portions of the Software.\n// \n//  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n//  THE SOFTWARE.\n//  ---------------------------------------------------------------------------------\n\n// based on https://github.com/microsoft/Windows.UI.Composition-Win32-Samples/blob/master/dotnet/WPF/ScreenCapture/Composition.WindowsRuntimeHelpers/Direct3D11Helper.cs\n\nusing System;\nusing System.Runtime.InteropServices;\nusing Windows.Graphics.DirectX.Direct3D11;\nusing SharpDX.Direct3D;\nusing SharpDX.Direct3D11;\nusing SharpDX.DXGI;\nusing Device = SharpDX.Direct3D11.Device;\nusing Device3 = SharpDX.DXGI.Device3;\n#if NET5_0_OR_GREATER\nusing WinRT;\n#endif\n\nnamespace ScreenCapture\n{\n    public static class Direct3D11Helper\n    {\n        private static          Guid IInspectable    = new( \"AF86E2E0-B12D-4c6a-9C5A-D7AA65101E90\" );\n        private static          Guid ID3D11Resource  = new( \"dc8e63f3-d12b-4952-b47b-5e45026a862d\" );\n        private static          Guid IDXGIAdapter3   = new( \"645967A4-1392-4310-A798-8053CE3E93FD\" );\n        private static readonly Guid ID3D11Device    = new( \"db6f6ddb-ac77-4e88-8253-819df9bbf140\" );\n        private static readonly Guid ID3D11Texture2D = new( \"6f15aaf2-d208-4e89-9ab4-489535d34f9c\" );\n\n        [DllImport(\n            \"d3d11.dll\",\n            EntryPoint = \"CreateDirect3D11DeviceFromDXGIDevice\",\n            SetLastError = true,\n            CharSet = CharSet.Unicode,\n            ExactSpelling = true,\n            CallingConvention = CallingConvention.StdCall\n        )]\n        private static extern uint CreateDirect3D11DeviceFromDXGIDevice( IntPtr dxgiDevice, out IntPtr graphicsDevice );\n\n        [DllImport(\n            \"d3d11.dll\",\n            EntryPoint = \"CreateDirect3D11SurfaceFromDXGISurface\",\n            SetLastError = true,\n            CharSet = CharSet.Unicode,\n            ExactSpelling = true,\n            CallingConvention = CallingConvention.StdCall\n        )]\n        private static extern uint CreateDirect3D11SurfaceFromDXGISurface( IntPtr dxgiSurface, out IntPtr graphicsSurface );\n\n        public static IDirect3DDevice CreateDevice()\n        {\n            return CreateDevice( false );\n        }\n\n        public static IDirect3DDevice CreateDevice( bool useWARP )\n        {\n            var d3dDevice = new Device(\n                useWARP ? DriverType.Software : DriverType.Hardware,\n                DeviceCreationFlags.BgraSupport );\n            var device = CreateDirect3DDeviceFromSharpDXDevice( d3dDevice );\n            return device;\n        }\n\n        public static IDirect3DDevice CreateDirect3DDeviceFromSharpDXDevice( Device d3dDevice )\n        {\n            IDirect3DDevice device = null;\n\n            // Acquire the DXGI interface for the Direct3D device.\n            using ( var dxgiDevice = d3dDevice.QueryInterface<Device3>() )\n            {\n                // Wrap the native device using a WinRT interop object.\n                var hr = CreateDirect3D11DeviceFromDXGIDevice( dxgiDevice.NativePointer, out var pUnknown );\n\n                if ( hr == 0 )\n                {\n#if NET5_0_OR_GREATER\n                    device = MarshalInterface<IDirect3DDevice>.FromAbi( pUnknown );\n#else\n                    device = Marshal.GetObjectForIUnknown( pUnknown ) as IDirect3DDevice;\n#endif\n                    Marshal.Release( pUnknown );\n                }\n            }\n\n            return device;\n        }\n\n        public static IDirect3DSurface CreateDirect3DSurfaceFromSharpDXTexture( Texture2D texture )\n        {\n            IDirect3DSurface surface = null;\n\n            // Acquire the DXGI interface for the Direct3D surface.\n            using ( var dxgiSurface = texture.QueryInterface<Surface>() )\n            {\n                // Wrap the native device using a WinRT interop object.\n                var hr = CreateDirect3D11SurfaceFromDXGISurface( dxgiSurface.NativePointer, out var pUnknown );\n\n                if ( hr == 0 )\n                {\n#if NET5_0_OR_GREATER\n                    surface = MarshalInterface<IDirect3DSurface>.FromAbi( pUnknown );\n#else\n                    surface = Marshal.GetObjectForIUnknown( pUnknown ) as IDirect3DSurface;\n#endif\n                    Marshal.Release( pUnknown );\n                }\n            }\n\n            return surface;\n        }\n\n        public static Device CreateSharpDXDevice( IDirect3DDevice device )\n        {\n#if NET5_0_OR_GREATER\n            var access = device.As<IDirect3DDxgiInterfaceAccess>();\n#else\n            var access = (IDirect3DDxgiInterfaceAccess)device;\n#endif\n            var d3dPointer = access.GetInterface( ID3D11Device );\n            var d3dDevice  = new Device( d3dPointer );\n            return d3dDevice;\n        }\n\n        public static Texture2D CreateSharpDXTexture2D( IDirect3DSurface surface )\n        {\n#if NET5_0_OR_GREATER\n            var access = surface.As<IDirect3DDxgiInterfaceAccess>();\n#else\n            var access = (IDirect3DDxgiInterfaceAccess)surface;\n#endif\n            var d3dPointer = access.GetInterface( ID3D11Texture2D );\n            var d3dSurface = new Texture2D( d3dPointer );\n            return d3dSurface;\n        }\n\n        [ComImport]\n        [Guid( \"A9B3D012-3DF2-4EE3-B8D1-8695F457D3C1\" )]\n        [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n        [ComVisible( true )]\n        private interface IDirect3DDxgiInterfaceAccess\n        {\n            IntPtr GetInterface( [In] ref Guid iid );\n        };\n    }\n}"
  },
  {
    "path": "Plugins.sln/ScreenCapture/FrameProcessor.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of Cube3D.\n\nCube3D is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nCube3D is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with Cube3D. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\n\nnamespace ScreenCapture\n{\n    public abstract class FrameProcessor\n    {\n        public abstract void Proceed( IntPtr pointer, ulong frameNumber );\n    }\n}"
  },
  {
    "path": "Plugins.sln/ScreenCapture/MonitorEnumerationHelper.cs",
    "content": "﻿//  ---------------------------------------------------------------------------------\n//  Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n//  The MIT License (MIT)\n// \n//  Permission is hereby granted, free of charge, to any person obtaining a copy\n//  of this software and associated documentation files (the \"Software\"), to deal\n//  in the Software without restriction, including without limitation the rights\n//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n//  copies of the Software, and to permit persons to whom the Software is\n//  furnished to do so, subject to the following conditions:\n// \n//  The above copyright notice and this permission notice shall be included in\n//  all copies or substantial portions of the Software.\n// \n//  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n//  THE SOFTWARE.\n//  ---------------------------------------------------------------------------------\n\nusing System;\nusing System.Collections.Generic;\nusing System.Numerics;\nusing System.Runtime.InteropServices;\nusing Windows.Foundation;\n\nnamespace ScreenCapture\n{\n    public class MonitorInfo\n    {\n        public bool    IsPrimary   { get; set; }\n        public Vector2 ScreenSize  { get; set; }\n        public Rect    MonitorArea { get; set; }\n        public Rect    WorkArea    { get; set; }\n        public string  DeviceName  { get; set; }\n        public IntPtr  Hmon        { get; set; }\n    }\n\n    public static class MonitorEnumerationHelper\n    {\n        private const int CCHDEVICENAME = 32;\n\n        [DllImport( \"user32.dll\" )]\n        private static extern bool EnumDisplayMonitors( IntPtr hdc, IntPtr lprcClip, EnumMonitorsDelegate lpfnEnum, IntPtr dwData );\n\n        [DllImport( \"user32.dll\", CharSet = CharSet.Auto )]\n        private static extern bool GetMonitorInfo( IntPtr hMonitor, ref MonitorInfoEx lpmi );\n\n        public static IEnumerable<MonitorInfo> GetMonitors()\n        {\n            var result = new List<MonitorInfo>();\n\n            EnumDisplayMonitors( IntPtr.Zero, IntPtr.Zero,\n                delegate( IntPtr hMonitor, IntPtr hdcMonitor, ref RECT lprcMonitor, IntPtr dwData )\n                {\n                    var mi = new MonitorInfoEx();\n                    mi.Size = Marshal.SizeOf( mi );\n                    var success = GetMonitorInfo( hMonitor, ref mi );\n                    if ( success )\n                    {\n                        var info = new MonitorInfo\n                        {\n                            ScreenSize = new Vector2( mi.Monitor.right - mi.Monitor.left, mi.Monitor.bottom - mi.Monitor.top ),\n                            MonitorArea = new Rect( mi.Monitor.left, mi.Monitor.top, mi.Monitor.right - mi.Monitor.left, mi.Monitor.bottom - mi.Monitor.top ),\n                            WorkArea =\n                                new Rect( mi.WorkArea.left, mi.WorkArea.top, mi.WorkArea.right - mi.WorkArea.left, mi.WorkArea.bottom - mi.WorkArea.top ),\n                            IsPrimary = mi.Flags > 0,\n                            Hmon = hMonitor,\n                            DeviceName = mi.DeviceName\n                        };\n                        result.Add( info );\n                    }\n\n                    return true;\n                }, IntPtr.Zero );\n            return result;\n        }\n\n        private delegate bool EnumMonitorsDelegate( IntPtr hMonitor, IntPtr hdcMonitor, ref RECT lprcMonitor, IntPtr dwData );\n\n        [StructLayout( LayoutKind.Sequential )]\n        public struct RECT\n        {\n            public int left;\n            public int top;\n            public int right;\n            public int bottom;\n        }\n\n        [StructLayout( LayoutKind.Sequential, CharSet = CharSet.Auto )]\n        internal struct MonitorInfoEx\n        {\n            public int  Size;\n            public RECT Monitor;\n            public RECT WorkArea;\n            public uint Flags;\n\n            [MarshalAs( UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME )]\n            public string DeviceName;\n        }\n    }\n}"
  },
  {
    "path": "Plugins.sln/ScreenCapture/ScreenCapture.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFrameworks>net6.0-windows10.0.20348.0;net6.0-windows10.0.22000.0;</TargetFrameworks>\n    </PropertyGroup>\n\n    <ItemGroup>\n        <PackageReference Include=\"SharpDX.Direct3D11\" Version=\"4.2.0\" />\n        <PackageReference Include=\"SharpDX.Direct3D9\" Version=\"4.2.0\" />\n        <PackageReference Include=\"System.Numerics.Vectors\" Version=\"4.5.0\" />\n    </ItemGroup>\n\n    <ItemGroup Condition=\" '$(TargetFramework)' == 'netcoreapp3.1' \">\n        <PackageReference Include=\"Microsoft.Windows.SDK.Contracts\" Version=\"10.0.22000.196\" />\n    </ItemGroup>\n\n    <ItemGroup>\n        <PackageReference Include=\"Microsoft.CodeAnalysis.NetAnalyzers\" Version=\"6.0.0\">\n            <PrivateAssets>all</PrivateAssets>\n            <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n        </PackageReference>\n    </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "Plugins.sln/ScreenCapture/WindowEnumerationHelper.cs",
    "content": "﻿//  ---------------------------------------------------------------------------------\n//  Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n//  The MIT License (MIT)\n// \n//  Permission is hereby granted, free of charge, to any person obtaining a copy\n//  of this software and associated documentation files (the \"Software\"), to deal\n//  in the Software without restriction, including without limitation the rights\n//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n//  copies of the Software, and to permit persons to whom the Software is\n//  furnished to do so, subject to the following conditions:\n// \n//  The above copyright notice and this permission notice shall be included in\n//  all copies or substantial portions of the Software.\n// \n//  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n//  THE SOFTWARE.\n//  ---------------------------------------------------------------------------------\n\nusing System;\nusing System.Runtime.InteropServices;\n\nnamespace ScreenCapture\n{\n    internal static class WindowEnumerationHelper\n    {\n        public enum GWL\n        {\n            GWL_WNDPROC    = -4,\n            GWL_HINSTANCE  = -6,\n            GWL_HWNDPARENT = -8,\n            GWL_STYLE      = -16,\n            GWL_EXSTYLE    = -20,\n            GWL_USERDATA   = -21,\n            GWL_ID         = -12\n        }\n\n        [DllImport( \"user32.dll\" )]\n        private static extern IntPtr GetShellWindow();\n\n        [DllImport( \"user32.dll\" )]\n        [return: MarshalAs( UnmanagedType.Bool )]\n        private static extern bool IsWindowVisible( IntPtr hWnd );\n\n        [DllImport( \"user32.dll\", ExactSpelling = true )]\n        private static extern IntPtr GetAncestor( IntPtr hwnd, GetAncestorFlags flags );\n\n        [DllImport( \"user32.dll\", EntryPoint = \"GetWindowLong\" )]\n        private static extern IntPtr GetWindowLongPtr32( IntPtr hWnd, int nIndex );\n\n        [DllImport( \"user32.dll\", EntryPoint = \"GetWindowLongPtr\" )]\n        private static extern IntPtr GetWindowLongPtr64( IntPtr hWnd, int nIndex );\n\n        // This static method is required because Win32 does not support\n        // GetWindowLongPtr directly.\n        // http://pinvoke.net/default.aspx/user32/GetWindowLong.html\n        private static IntPtr GetWindowLongPtr( IntPtr hWnd, int nIndex )\n        {\n            if ( IntPtr.Size == 8 )\n                return GetWindowLongPtr64( hWnd, nIndex );\n            else\n                return GetWindowLongPtr32( hWnd, nIndex );\n        }\n\n        [DllImport( \"dwmapi.dll\" )]\n        private static extern int DwmGetWindowAttribute( IntPtr hwnd, DWMWINDOWATTRIBUTE dwAttribute, out bool pvAttribute, int cbAttribute );\n\n        public static bool IsWindowValidForCapture( IntPtr hwnd )\n        {\n            if ( hwnd.ToInt32() == 0 )\n            {\n                return false;\n            }\n\n            if ( hwnd == GetShellWindow() )\n            {\n                return false;\n            }\n\n            if ( !IsWindowVisible( hwnd ) )\n            {\n                return false;\n            }\n\n            if ( GetAncestor( hwnd, GetAncestorFlags.GetRoot ) != hwnd )\n            {\n                return false;\n            }\n\n            var style = (WindowStyles)(uint)GetWindowLongPtr( hwnd, (int)GWL.GWL_STYLE ).ToInt32();\n            if ( style.HasFlag( WindowStyles.WS_DISABLED ) )\n            {\n                return false;\n            }\n\n            var cloaked = false;\n            var hrTemp  = DwmGetWindowAttribute( hwnd, DWMWINDOWATTRIBUTE.Cloaked, out cloaked, Marshal.SizeOf<bool>() );\n            if ( hrTemp == 0 && cloaked )\n            {\n                return false;\n            }\n\n            return true;\n        }\n\n        private enum GetAncestorFlags\n        {\n            // Retrieves the parent window. This does not include the owner, as it does with the GetParent function.\n            GetParent = 1,\n\n            // Retrieves the root window by walking the chain of parent windows.\n            GetRoot = 2,\n\n            // Retrieves the owned root window by walking the chain of parent and owner windows returned by GetParent.\n            GetRootOwner = 3\n        }\n\n        [Flags]\n        private enum WindowStyles : uint\n        {\n            WS_BORDER           = 0x800000,\n            WS_CAPTION          = 0xc00000,\n            WS_CHILD            = 0x40000000,\n            WS_CLIPCHILDREN     = 0x2000000,\n            WS_CLIPSIBLINGS     = 0x4000000,\n            WS_DISABLED         = 0x8000000,\n            WS_DLGFRAME         = 0x400000,\n            WS_GROUP            = 0x20000,\n            WS_HSCROLL          = 0x100000,\n            WS_MAXIMIZE         = 0x1000000,\n            WS_MAXIMIZEBOX      = 0x10000,\n            WS_MINIMIZE         = 0x20000000,\n            WS_MINIMIZEBOX      = 0x20000,\n            WS_OVERLAPPED       = 0x0,\n            WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_SIZEFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,\n            WS_POPUP            = 0x80000000u,\n            WS_POPUPWINDOW      = WS_POPUP | WS_BORDER | WS_SYSMENU,\n            WS_SIZEFRAME        = 0x40000,\n            WS_SYSMENU          = 0x80000,\n            WS_TABSTOP          = 0x10000,\n            WS_VISIBLE          = 0x10000000,\n            WS_VSCROLL          = 0x200000\n        }\n\n        private enum DWMWINDOWATTRIBUTE : uint\n        {\n            NCRenderingEnabled = 1,\n            NCRenderingPolicy,\n            TransitionsForceDisabled,\n            AllowNCPaint,\n            CaptionButtonBounds,\n            NonClientRtlLayout,\n            ForceIconicRepresentation,\n            Flip3DPolicy,\n            ExtendedFrameBounds,\n            HasIconicBitmap,\n            DisallowPeek,\n            ExcludedFromPeek,\n            Cloak,\n            Cloaked,\n            FreezeRepresentation\n        }\n    }\n}"
  },
  {
    "path": "Plugins.sln/Updater/AutoVersion.tt",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of Updater.\n\nUpdater is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nUpdater is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with Updater. If not, see <https://www.gnu.org/licenses/>.\n*/\n\n<#@ template debug=\"false\" hostspecific=\"false\" language=\"C#\" #>\n<#@ output extension=\".cs\" #>\n\n<#@ Assembly Name=\"System.Core.dll\" #>\n<#@ Assembly Name=\"System.Windows.Forms.dll\" #>\n<#@ import namespace=\"System.IO\" #>\n\nusing System.Reflection;\n\n[assembly: AssemblyProduct(\"<#= AppName #>\")]\n\n[assembly: AssemblyTitle(\"<#= AppDesc #>\")]\n[assembly: AssemblyDescription(\"<#= AppDesc #>\")]\n\n[assembly: AssemblyCompany(\"https://github.com/newlooper\")]\n\n[assembly: AssemblyCopyright(\"Copyright © <#= Copyright #>\")]\n\n[assembly: AssemblyVersion(\"<#= MAJOR #>.<#= MINOR #>.<#= DaysSinceProjectStarted #>.<#= MinutesSinceMidnight #>\")]\n[assembly: AssemblyFileVersion(\"<#= MAJOR #>.<#= MINOR #>.<#= DaysSinceProjectStarted #>.<#= MinutesSinceMidnight #>\")]\n\n<#+\n    private static readonly DateTime ProjectStartedDate = new( 2022, 12, 22 );\n\n    private static readonly string Copyright = ProjectStartedDate.Year + \" - \" + DateTime.Now.Year;\n    private static readonly string AppName = new DirectoryInfo( \".\" ).Name;\n    private static readonly string AppDesc = \"VirtualSpace.Plugin - Updater\";\n\n        private const int MAJOR = 1;\n        private const int MINOR = 0;\n\n    private static readonly int DaysSinceProjectStarted = (int)( DateTime.UtcNow - ProjectStartedDate ).TotalDays;\n    private static readonly int MinutesSinceMidnight = (int)DateTime.UtcNow.TimeOfDay.TotalMinutes;\n#>"
  },
  {
    "path": "Plugins.sln/Updater/COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "Plugins.sln/Updater/Config/Const.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n//\n// This file is part of Updater.\n//\n// Updater is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n//\n// Updater is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License along with Updater. If not, see <https://www.gnu.org/licenses/>.\n\nnamespace Updater.Config;\n\npublic static class Const\n{\n    public const string HttpHeaderUserAgent    = \"User-Agent\";\n    public const string HttpUserAgent          = \"C# App\";\n    public const string GitHubApiLatestRelease = \"https://api.github.com/repos/newlooper/VirtualSpace/releases/latest\";\n    public const string PatternTag             = @\"\"\"tag_name\"\": ?\"\"(.*?)\"\"\";\n    public const string PatternVersion         = @\"\\d+\\.\\d+\\.\\d+(\\.\\d+)?\";\n    public const string PatternDownloadUrl     = @\"\"\"browser_download_url\"\": ?\"\"(.*?)\"\"\";\n    public const string DownloadZip            = \"download.zip\";\n    public const int    WaitInterval           = 500;\n}"
  },
  {
    "path": "Plugins.sln/Updater/HttpClientProgress.cs",
    "content": "﻿namespace Updater;\n\n// https://gist.github.com/dalexsoto/9fd3c5bdbe9f61a717d47c5843384d11\n\npublic static class HttpClientProgressExtensions\n{\n    public static async Task DownloadDataAsync( this HttpClient client,\n        string                                                  requestUrl,\n        Stream                                                  destination,\n        IProgress<float>                                        progress          = null,\n        CancellationToken                                       cancellationToken = default )\n    {\n        using var       response       = await client.GetAsync( requestUrl, HttpCompletionOption.ResponseHeadersRead, cancellationToken );\n        var             contentLength  = response.Content.Headers.ContentLength;\n        await using var downloadStream = await response.Content.ReadAsStreamAsync( cancellationToken );\n\n        // no progress... no contentLength... very sad\n        if ( progress is null || !contentLength.HasValue )\n        {\n            await downloadStream.CopyToAsync( destination, cancellationToken );\n            return;\n        }\n\n        // Such progress and contentLength much reporting!\n        float GetProgressPercentage( float read, float total )\n        {\n            return read / total * 100f;\n        }\n\n        var progressWrapper = new Progress<long>( bytes => progress.Report( GetProgressPercentage( bytes, contentLength.Value ) ) );\n        await downloadStream.CopyToAsync( destination, 81920, progressWrapper, cancellationToken );\n    }\n\n    private static async Task CopyToAsync( this Stream source,\n        Stream                                         destination,\n        int                                            bufferSize,\n        IProgress<long>                                progress          = null,\n        CancellationToken                              cancellationToken = default )\n    {\n        if ( bufferSize < 0 )\n            throw new ArgumentOutOfRangeException( nameof( bufferSize ) );\n        if ( source is null )\n            throw new ArgumentNullException( nameof( source ) );\n        if ( !source.CanRead )\n            throw new InvalidOperationException( $\"'{nameof( source )}' is not readable.\" );\n        if ( destination == null )\n            throw new ArgumentNullException( nameof( destination ) );\n        if ( !destination.CanWrite )\n            throw new InvalidOperationException( $\"'{nameof( destination )}' is not writable.\" );\n\n        var  buffer         = new byte[bufferSize];\n        long totalBytesRead = 0;\n        int  bytesRead;\n        while ( ( bytesRead = await source.ReadAsync( buffer, cancellationToken ).ConfigureAwait( false ) ) != 0 )\n        {\n            await destination.WriteAsync( buffer.AsMemory( 0, bytesRead ), cancellationToken ).ConfigureAwait( false );\n            totalBytesRead += bytesRead;\n            progress?.Report( totalBytesRead );\n        }\n    }\n}"
  },
  {
    "path": "Plugins.sln/Updater/MainForm.Designer.cs",
    "content": "﻿namespace Updater\n{\n    partial class MainForm\n    {\n        /// <summary>\n        ///  Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        ///  Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Windows Form Designer generated code\n\n        /// <summary>\n        ///  Required method for Designer support - do not modify\n        ///  the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            progbarDownload = new ProgressBar();\n            tableLayoutPanel1 = new TableLayoutPanel();\n            lb_progress = new Label();\n            tableLayoutPanel1.SuspendLayout();\n            SuspendLayout();\n            // \n            // progbarDownload\n            // \n            progbarDownload.Dock = DockStyle.Fill;\n            progbarDownload.Location = new Point(10, 60);\n            progbarDownload.Margin = new Padding(10);\n            progbarDownload.Name = \"progbarDownload\";\n            progbarDownload.Size = new Size(480, 30);\n            progbarDownload.TabIndex = 0;\n            // \n            // tableLayoutPanel1\n            // \n            tableLayoutPanel1.ColumnCount = 1;\n            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));\n            tableLayoutPanel1.Controls.Add(progbarDownload, 0, 1);\n            tableLayoutPanel1.Controls.Add(lb_progress, 0, 0);\n            tableLayoutPanel1.Dock = DockStyle.Fill;\n            tableLayoutPanel1.Location = new Point(0, 0);\n            tableLayoutPanel1.Name = \"tableLayoutPanel1\";\n            tableLayoutPanel1.RowCount = 2;\n            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));\n            tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));\n            tableLayoutPanel1.Size = new Size(500, 100);\n            tableLayoutPanel1.TabIndex = 1;\n            // \n            // lb_progress\n            // \n            lb_progress.AutoSize = true;\n            lb_progress.Dock = DockStyle.Fill;\n            lb_progress.Location = new Point(10, 10);\n            lb_progress.Margin = new Padding(10);\n            lb_progress.Name = \"lb_progress\";\n            lb_progress.Size = new Size(480, 30);\n            lb_progress.TabIndex = 1;\n            lb_progress.TextAlign = ContentAlignment.MiddleCenter;\n            // \n            // MainForm\n            // \n            AutoScaleDimensions = new SizeF(7F, 17F);\n            AutoScaleMode = AutoScaleMode.Font;\n            ClientSize = new Size(500, 100);\n            Controls.Add(tableLayoutPanel1);\n            FormBorderStyle = FormBorderStyle.None;\n            Margin = new Padding(2);\n            Name = \"MainForm\";\n            StartPosition = FormStartPosition.CenterScreen;\n            Text = \"MainForm\";\n            TopMost = true;\n            Load += MainForm_Load;\n            tableLayoutPanel1.ResumeLayout(false);\n            tableLayoutPanel1.PerformLayout();\n            ResumeLayout(false);\n        }\n\n        #endregion\n\n        private ProgressBar progbarDownload;\n        private TableLayoutPanel tableLayoutPanel1;\n        private Label lb_progress;\n    }\n}"
  },
  {
    "path": "Plugins.sln/Updater/MainForm.cs",
    "content": "// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n//\n// This file is part of Updater.\n//\n// Updater is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n//\n// Updater is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License along with Updater. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.IO.Compression;\nusing System.Reflection;\nusing System.Resources;\nusing System.Text.RegularExpressions;\nusing Updater.Config;\nusing VirtualSpace.Commons;\nusing VirtualSpace.Plugin;\n\nnamespace Updater\n{\n    public partial class MainForm : Form\n    {\n        private static readonly ResourceManager Langs = new(\n            Assembly.GetExecutingAssembly().GetName().Name + \".Resources.Langs.WinFormStrings\",\n            typeof( MainForm ).Assembly );\n\n        public MainForm()\n        {\n            InitializeComponent();\n        }\n\n        protected override void OnLoad( EventArgs e )\n        {\n            Visible = false; // Hide form window.\n            ShowInTaskbar = false; // Remove from taskbar.\n\n            base.OnLoad( e );\n        }\n\n        private void MainForm_Load( object sender, EventArgs e )\n        {\n            var pipeMessage = new PipeMessage\n            {\n                Type = PipeMessageType.PLUGIN_UPDATER,\n                Name = PluginManager.PluginInfo.Name,\n                Handle = Handle.ToInt32()\n            };\n\n            try\n            {\n                IpcPipeClient.PluginCheckIn<HostInfo>(\n                    pipeMessage,\n                    () => { MessageBox.Show( Langs.GetString( \"Error.CheckHost\" ) ); },\n                    Application.Exit,\n                    CheckUpdate\n                );\n            }\n            catch\n            {\n                Application.Exit();\n            }\n        }\n\n        private async void CheckUpdate( HostInfo hostInfo )\n        {\n            try\n            {\n                using var httpClient = new HttpClient();\n                httpClient.DefaultRequestHeaders.Add( Const.HttpHeaderUserAgent, Const.HttpUserAgent );\n\n                var jsonReleaseInfo = await httpClient.GetStringAsync( Const.GitHubApiLatestRelease );\n                var mTag            = Regex.Match( jsonReleaseInfo, Const.PatternTag );\n                if ( !mTag.Success ) throw new Exception( \"release info not found.\" );\n\n                var mVer = Regex.Match( mTag.Groups[1].Value, Const.PatternVersion );\n                if ( !mVer.Success ) throw new Exception( \"version info not found.\" );\n\n                var latestVersion = new Version( mVer.Groups[0].Value );\n                if ( latestVersion <= hostInfo.Version ) throw new Exception( \"no update.\" );\n\n                var dialogResult = MessageBox.Show( string.Format( Langs.GetString( \"Updater.Confirm\" ), hostInfo.Product, latestVersion, hostInfo.Version ),\n                    Langs.GetString( \"Updater.Confirm.Title\" ),\n                    MessageBoxButtons.YesNo,\n                    MessageBoxIcon.Information );\n                if ( !dialogResult.Equals( DialogResult.Yes ) && !dialogResult.Equals( DialogResult.OK ) ) throw new Exception( \"user canceled.\" );\n\n                var mcUrls = Regex.Matches( jsonReleaseInfo, Const.PatternDownloadUrl );\n                var zipUrl = \"\";\n                foreach ( Match mUrl in mcUrls )\n                {\n                    var url = mUrl.Groups[1].Value;\n                    if ( url.Contains( \"noplugin\" ) )\n                    {\n                        zipUrl = url;\n                        break;\n                    }\n                }\n\n                if ( string.IsNullOrEmpty( zipUrl ) ) throw new Exception( \"file url not found.\" );\n\n                Visible = true;\n\n                var downloadZip = Path.Combine( PluginManager.GetAppFolder(), Const.DownloadZip );\n\n                var progress = new Progress<float>();\n                progress.ProgressChanged += ( s, progressValue ) => { progbarDownload.Value = (int)progressValue; };\n\n                lb_progress.Text = Langs.GetString( \"Progress.Downloading\" );\n                if ( File.Exists( downloadZip ) ) File.Delete( downloadZip );\n\n                await using var file = new FileStream( downloadZip, FileMode.Create, FileAccess.Write, FileShare.None );\n                await httpClient.DownloadDataAsync( zipUrl, file, progress );\n                file.Close();\n\n                while ( progbarDownload.Value < 100 )\n                {\n                    await Task.Delay( Const.WaitInterval );\n                }\n\n                lb_progress.Text = Langs.GetString( \"Progress.Clean\" );\n                await Task.Delay( Const.WaitInterval );\n\n                var exeInZip = hostInfo.Product + \".exe\";\n                var backup   = hostInfo.AppPath + \".bak\";\n\n                if ( File.Exists( backup ) ) File.Delete( backup );\n\n                lb_progress.Text = Langs.GetString( \"Progress.Extract\" );\n                await Task.Delay( Const.WaitInterval );\n\n                using var zip = ZipFile.Open( downloadZip, ZipArchiveMode.Read );\n                foreach ( var entry in zip.Entries )\n                {\n                    if ( !entry.Name.Contains( exeInZip ) ) continue;\n                    File.Move( hostInfo.AppPath, backup );\n                    entry.ExtractToFile( hostInfo.AppPath );\n\n                    lb_progress.Text = Langs.GetString( \"Progress.NotifyHostRestart\" );\n                    await Task.Delay( Const.WaitInterval );\n                    IpcPipeClient.NotifyHostRestart();\n\n                    break;\n                }\n\n                Visible = false;\n            }\n            catch\n            {\n                // ignored\n            }\n            finally\n            {\n                Application.Exit();\n            }\n        }\n    }\n}"
  },
  {
    "path": "Plugins.sln/Updater/MainForm.resx",
    "content": "﻿<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n</root>"
  },
  {
    "path": "Plugins.sln/Updater/Program.cs",
    "content": "// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n//\n// This file is part of Updater.\n//\n// Updater is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n//\n// Updater is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License along with Updater. If not, see <https://www.gnu.org/licenses/>.\n\nusing VirtualSpace.Plugin;\n\nnamespace Updater\n{\n    internal static class Program\n    {\n        /// <summary>\n        ///  The main entry point for the application.\n        /// </summary>\n        [STAThread]\n        static void Main()\n        {\n            // To customize application configuration such as set high DPI settings or default font,\n            // see https://aka.ms/applicationconfiguration.\n            ApplicationConfiguration.Initialize();\n            var pluginInfo = PluginManager.PluginInfo;\n            if ( pluginInfo == null || string.IsNullOrEmpty( pluginInfo.Name ) )\n            {\n                MessageBox.Show( $\"{PluginManager.PluginInfoFile} invalid.\" );\n            }\n            else\n            {\n                Application.Run( new MainForm() );\n            }\n        }\n    }\n}"
  },
  {
    "path": "Plugins.sln/Updater/Resources/Langs/WinFormStrings.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"Error.CheckHost\" xml:space=\"preserve\">\n    <value>This Program require VirtualSpace running first.</value>\n  </data>\n  <data name=\"Updater.Confirm\" xml:space=\"preserve\">\n    <value>New version of {0} {1} available, You are using {2} \nDo you want to update now?</value>\n  </data>\n  <data name=\"Updater.Confirm.Title\" xml:space=\"preserve\">\n    <value>Update Available</value>\n  </data>\n  <data name=\"Progress.Downloading\" xml:space=\"preserve\">\n    <value>Downloading...</value>\n  </data>\n  <data name=\"Progress.Clean\" xml:space=\"preserve\">\n    <value>Clean Old Files...</value>\n  </data>\n  <data name=\"Progress.Extract\" xml:space=\"preserve\">\n    <value>Extract Files...</value>\n  </data>\n  <data name=\"Progress.NotifyHostRestart\" xml:space=\"preserve\">\n    <value>Notify Host Restart.</value>\n  </data>\n</root>"
  },
  {
    "path": "Plugins.sln/Updater/Resources/Langs/WinFormStrings.zh-Hans.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"Error.CheckHost\" xml:space=\"preserve\">\n    <value>运行本程序需要先运行 VirtualSpace。</value>\n  </data>\n  <data name=\"Updater.Confirm\" xml:space=\"preserve\">\n    <value>新版本 {0} {1} 可用，当前运行的是 {2} \n是否执行更新？</value>\n  </data>\n  <data name=\"Updater.Confirm.Title\" xml:space=\"preserve\">\n    <value>有更新可用</value>\n  </data>\n  <data name=\"Progress.Downloading\" xml:space=\"preserve\">\n    <value>下载中...</value>\n  </data>\n  <data name=\"Progress.Clean\" xml:space=\"preserve\">\n    <value>清理旧文件...</value>\n  </data>\n  <data name=\"Progress.Extract\" xml:space=\"preserve\">\n    <value>解压中...</value>\n  </data>\n  <data name=\"Progress.NotifyHostRestart\" xml:space=\"preserve\">\n    <value>通知主程序重启</value>\n  </data>\n</root>"
  },
  {
    "path": "Plugins.sln/Updater/Updater.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <OutputType>WinExe</OutputType>\n        <TargetFramework>net6.0-windows</TargetFramework>\n        <Nullable>enable</Nullable>\n        <UseWindowsForms>true</UseWindowsForms>\n        <ImplicitUsings>enable</ImplicitUsings>\n    </PropertyGroup>\n\n    <PropertyGroup>\n        <GenerateAssemblyInfo>false</GenerateAssemblyInfo>\n        <OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles>\n    </PropertyGroup>\n\n    <Target Name=\"TextTemplateTransform\" BeforeTargets=\"BeforeBuild\" Condition=\"'$(Configuration)'=='Release'\">\n        <Message Text=\"======TextTemplateTransform begin======\" Importance=\"High\" />\n        <Exec WorkingDirectory=\"$(ProjectDir)\" \n              Command=\"&quot;$(DevEnvDir)TextTransform.exe&quot; -out &quot;$(ProjectDir)AutoVersion.cs&quot; &quot;$(ProjectDir)AutoVersion.tt&quot;\">\n            <Output TaskParameter=\"ConsoleOutput\" PropertyName=\"OutputOfExec\" />\n        </Exec>\n        <Message Text=\"======TextTemplateTransform end======\" Importance=\"High\" />\n    </Target>\n\n    <ItemGroup>\n        <Compile Update=\"AutoVersion.cs\">\n            <DesignTime>True</DesignTime>\n            <DependentUpon>AutoVersion.tt</DependentUpon>\n        </Compile>\n    </ItemGroup>\n\n    <ItemGroup>\n        <ProjectReference Include=\"..\\..\\Ipc\\IpcClient\\IpcClient.csproj\" />\n        <ProjectReference Include=\"..\\..\\Plugin\\Commons\\Plugin.csproj\" />\n    </ItemGroup>\n\n    <ItemGroup>\n        <None Update=\"plugin.json\">\n            <CopyToOutputDirectory>Always</CopyToOutputDirectory>\n        </None>\n    </ItemGroup>\n\n</Project>"
  },
  {
    "path": "Plugins.sln/Updater/plugin.json",
    "content": "{\n  \"Name\": \"Updater\",\n  \"Display\": \"Updater\",\n  \"Version\": \"1.2\",\n  \"Author\": \"Dylan Cheng\",\n  \"Email\": \"newlooper@hotmail.com\",\n  \"Entry\": \"Updater.exe\",\n  \"AutoStart\": true,\n  \"AutoStartTiming\": 0,\n  \"RestartPolicy\": {\n    \"Trigger\": 0,\n    \"Values\": [],\n    \"Enabled\": false\n  },\n  \"ClosePolicy\": {\n    \"Trigger\": 0,\n    \"Values\": [],\n    \"Enabled\": false\n  },\n  \"Requirements\": {\n    \"WinVer\": {\n      \"Min\": {\n        \"Major\": 10,\n        \"Build\": 19041\n      }\n    },\n    \"HostVersion\": \"0.1.454\"\n  }\n}"
  },
  {
    "path": "Readme.md",
    "content": "# VirtualSpace\n\n> A Virtual Desktop Enhancement GUI Program For Win10 & Win11\n\n[![License](https://img.shields.io/github/license/newlooper/VirtualSpace \"License\")](https://github.com/newlooper/VirtualSpace/blob/main/COPYING)\n[![Download Lastest](https://img.shields.io/github/v/release/newlooper/VirtualSpace \"Download Lastest\")](https://github.com/newlooper/VirtualSpace/releases)\n[![Total Downloads](https://img.shields.io/github/downloads/newlooper/VirtualSpace/total \"Total Downloads\")](https://github.com/newlooper/VirtualSpace/releases)\n\n## 1. Intro\n\n### 1.1 Design memo\n\ncn: https://newlooper.com/post/original/cs/os/windows/virtualdesktop/\n\n## 2. Download & Installation\n\nDownload from [Releases](https://github.com/newlooper/VirtualSpace/releases) page.\n\nVirtualSpace is green software, All used files are in its own directory, just unzip to a local dir (eg. `your desktop`\\VirtualSpace) and run.\n\nor build the program yourself (see below).\n\n## 3. Build\n\n> Suggested Target Platform `x64`\n\n### 3.1 main program\n\n- build VirtualSpace\n\n> Note\n> \n> WinForms\\AppController is currently not used by VirtualSpace, you may unload it in your IDE\n\n### 3.2 plugins\n\n- Cube3D —— plugin for virtual desktop switch effects\n  - build Cube3D project\n  - put `all generated files` into main program's plugins Folder eg: `plugins\\Cube3D`\n  - Run Cube3D.exe after VirtualSpace started\n\n## 4. HowTo\n\n### 4.1 Default Hotkey\n\n- LWin+Tab  ——  rise main view\n- Ctrl+Alt+F12  ——  config panel\n- LWin+LCtrl+<↑ ↓ ← →>  ——  switch virtual desktop\n\n## 5. Q&A\n\n- Q1: Why hotkey not working sometimes.\n- A1: This is usually due to Windows UIPI (UAC).\n- S1: Run VirtualSpace as Administrator to fix this.\n\n[Others](https://github.com/newlooper/VirtualSpace/issues?q=is%3Aissue)\n\n## 6. Demos\n\n### Video\n\n[![](https://res.cloudinary.com/marcomontalbano/image/upload/v1662744032/video_to_markdown/images/youtube--aFUo2kLYUy0-c05b58ac6eb4c4700831b2b3070cd403.jpg)](https://www.youtube.com/watch?v=aFUo2kLYUy0 \"\")\n\n### Image\n\n![05](https://github.com/newlooper/images/blob/main/VirtualSpace/05-SwitchVirtualDesktopInDirecti.gif?raw=true '05')"
  },
  {
    "path": "Resources/COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "Resources/Images.Designer.cs",
    "content": "﻿//------------------------------------------------------------------------------\n// <auto-generated>\n//     此代码由工具生成。\n//     运行时版本:4.0.30319.42000\n//\n//     对此文件的更改可能会导致不正确的行为，并且如果\n//     重新生成代码，这些更改将会丢失。\n// </auto-generated>\n//------------------------------------------------------------------------------\n\nnamespace Resources {\n    using System;\n    \n    \n    /// <summary>\n    ///   一个强类型的资源类，用于查找本地化的字符串等。\n    /// </summary>\n    // 此类是由 StronglyTypedResourceBuilder\n    // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。\n    // 若要添加或移除成员，请编辑 .ResX 文件，然后重新运行 ResGen\n    // (以 /str 作为命令选项)，或重新生成 VS 项目。\n    [global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Resources.Tools.StronglyTypedResourceBuilder\", \"17.0.0.0\")]\n    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]\n    internal class Images {\n        \n        private static global::System.Resources.ResourceManager resourceMan;\n        \n        private static global::System.Globalization.CultureInfo resourceCulture;\n        \n        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute(\"Microsoft.Performance\", \"CA1811:AvoidUncalledPrivateCode\")]\n        internal Images() {\n        }\n        \n        /// <summary>\n        ///   返回此类使用的缓存的 ResourceManager 实例。\n        /// </summary>\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\n        internal static global::System.Resources.ResourceManager ResourceManager {\n            get {\n                if (object.ReferenceEquals(resourceMan, null)) {\n                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager(\"Resources.Images\", typeof(Images).Assembly);\n                    resourceMan = temp;\n                }\n                return resourceMan;\n            }\n        }\n        \n        /// <summary>\n        ///   重写当前线程的 CurrentUICulture 属性，对\n        ///   使用此强类型资源类的所有资源查找执行重写。\n        /// </summary>\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\n        internal static global::System.Globalization.CultureInfo Culture {\n            get {\n                return resourceCulture;\n            }\n            set {\n                resourceCulture = value;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Resources/Images.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n</root>"
  },
  {
    "path": "Resources/Resources.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFrameworks>net6.0-windows</TargetFrameworks>\n        <Nullable>enable</Nullable>\n        <LangVersion>9</LangVersion>\n    </PropertyGroup>\n\n    <ItemGroup>\n        <Compile Update=\"Images.Designer.cs\">\n            <DesignTime>True</DesignTime>\n            <AutoGen>True</AutoGen>\n            <DependentUpon>Images.resx</DependentUpon>\n        </Compile>\n    </ItemGroup>\n\n    <ItemGroup>\n        <EmbeddedResource Update=\"Images.resx\">\n            <Generator>ResXFileCodeGenerator</Generator>\n            <LastGenOutput>Images.Designer.cs</LastGenOutput>\n        </EmbeddedResource>\n    </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "UiAutomation/COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "UiAutomation/UIA.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Windows.Automation;\n\nnamespace VirtualSpace.UIA\n{\n    public static class Uia\n    {\n        public static void CloseButtonInvokeByWindowHandle( IntPtr hWnd )\n        {\n            var window = AutomationElement.FromHandle( hWnd );\n            var closeButton = window?.FindFirst(\n                TreeScope.Descendants,\n                new PropertyCondition( AutomationElement.AutomationIdProperty, \"Close\" ) );\n            if ( closeButton != null )\n            {\n                var invokePattern = (InvokePattern)closeButton.GetCurrentPattern( InvokePattern.Pattern );\n                invokePattern.Invoke();\n            }\n        }\n    }\n}"
  },
  {
    "path": "UiAutomation/UiAutomation.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFrameworks>net6.0-windows</TargetFrameworks>\n        <LangVersion>9</LangVersion>\n        <UseWPF>true</UseWPF>\n        <Nullable>enable</Nullable>\n    </PropertyGroup>\n\n</Project>\n"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop10/COM.cs",
    "content": "﻿// Author: Markus Scholtes, 2021\n// Version 1.9, 2021-10-08\n// Version for Windows 10 1809 to 21H1\n// Compile with:\n// C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\csc.exe VirtualDesktop.cs\n// Based on http://stackoverflow.com/a/32417530, Windows 10 SDK, github project Grabacr07/VirtualDesktop and own research\n\n/////////////////////////////////////////////////\n// Dylan Cheng (https://github.com/newlooper)\n// added Notifications about desktop\n// added conditional compile for C#/WinRT breaking change on .NET 5.0+\n\nusing System;\nusing System.Runtime.InteropServices;\n\nnamespace VirtualDesktop\n{\n    internal static class Guids\n    {\n        public static readonly Guid CLSID_ImmersiveShell                    = new( \"C2F03A33-21F5-47FA-B4BB-156362A2F239\" );\n        public static readonly Guid CLSID_VirtualDesktopManagerInternal     = new( \"C5E0CDCA-7B6E-41B2-9FC4-D93975CC467B\" );\n        public static readonly Guid CLSID_VirtualDesktopManager             = new( \"AA509086-5CA9-4C25-8F95-589D3C07B48A\" );\n        public static readonly Guid CLSID_VirtualDesktopPinnedApps          = new( \"B5A399E7-1C87-46B8-88E9-FC5747B171BD\" );\n        public static readonly Guid CLSID_VirtualDesktopNotificationService = new( \"A501FDEC-4A09-464C-AE4E-1B9C21B84918\" );\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct Size\n    {\n        public int X;\n        public int Y;\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct Rect\n    {\n        public int Left;\n        public int Top;\n        public int Right;\n        public int Bottom;\n    }\n\n    public enum APPLICATION_VIEW_CLOAK_TYPE : int\n    {\n        AVCT_NONE            = 0,\n        AVCT_DEFAULT         = 1,\n        AVCT_VIRTUAL_DESKTOP = 2\n    }\n\n    public enum APPLICATION_VIEW_COMPATIBILITY_POLICY : int\n    {\n        AVCP_NONE                = 0,\n        AVCP_SMALL_SCREEN        = 1,\n        AVCP_TABLET_SMALL_SCREEN = 2,\n        AVCP_VERY_SMALL_SCREEN   = 3,\n        AVCP_HIGH_SCALE_FACTOR   = 4\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"372E1D3B-38D3-42E4-A15B-8AB2B178F513\" )]\n    public interface IApplicationView\n    {\n        void GetIIdsSlot();\n        void GetRuntimeClassNameSlot();\n        void GetTrustLevelSlot();\n        int  SetFocus();\n        int  SwitchTo();\n        int  TryInvokeBack( IntPtr /* IAsyncCallback* */ callback );\n        int  GetThumbnailWindow( out IntPtr hWnd );\n        int  GetMonitor( out         IntPtr /* IImmersiveMonitor */ immersiveMonitor );\n        int  GetVisibility( out      int visibility );\n        int  SetCloak( APPLICATION_VIEW_CLOAK_TYPE cloakType, int unknown );\n        int  GetPosition( ref Guid guid /* GUID for IApplicationViewPosition */, out IntPtr /* IApplicationViewPosition** */ position );\n        int  SetPosition( ref IntPtr /* IApplicationViewPosition* */ position );\n        int  InsertAfterWindow( IntPtr hWnd );\n        int  GetExtendedFramePosition( out                              Rect rect );\n        int  GetAppUserModelId( [MarshalAs( UnmanagedType.LPWStr )] out string id );\n        int  SetAppUserModelId( string id );\n        int  IsEqualByAppUserModelId( string id, out int result );\n        int  GetViewState( out uint state );\n        int  SetViewState( uint state );\n        int  GetNeediness( out               int neediness );\n        int  GetLastActivationTimestamp( out ulong timestamp );\n        int  SetLastActivationTimestamp( ulong timestamp );\n        int  GetVirtualDesktopId( out Guid guid );\n        int  SetVirtualDesktopId( ref Guid guid );\n        int  GetShowInSwitchers( out  int flag );\n        int  SetShowInSwitchers( int flag );\n        int  GetScaleFactor( out             int factor );\n        int  CanReceiveInput( out            bool canReceiveInput );\n        int  GetCompatibilityPolicyType( out APPLICATION_VIEW_COMPATIBILITY_POLICY flags );\n        int  SetCompatibilityPolicyType( APPLICATION_VIEW_COMPATIBILITY_POLICY flags );\n        int  GetSizeConstraints( IntPtr /* IImmersiveMonitor* */ monitor, out Size size1, out Size size2 );\n        int  GetSizeConstraintsForDpi( uint uint1, out Size size1, out Size size2 );\n        int  SetSizeConstraintsForDpi( ref uint uint1, ref Size size1, ref Size size2 );\n        int  OnMinSizePreferencesUpdated( IntPtr hWnd );\n        int  ApplyOperation( IntPtr /* IApplicationViewOperation* */ operation );\n        int  IsTray( out                  bool isTray );\n        int  IsInHighZOrderBand( out      bool isInHighZOrderBand );\n        int  IsSplashScreenPresented( out bool isSplashScreenPresented );\n        int  Flash();\n        int  GetRootSwitchableOwner( out                              IApplicationView rootSwitchableOwner );\n        int  EnumerateOwnershipTree( out                              IObjectArray     ownershipTree );\n        int  GetEnterpriseId( [MarshalAs( UnmanagedType.LPWStr )] out string           enterpriseId );\n        int  IsMirrored( out                                          bool             isMirrored );\n        int  Unknown1( out                                            int              unknown );\n        int  Unknown2( out                                            int              unknown );\n        int  Unknown3( out                                            int              unknown );\n        int  Unknown4( out                                            int              unknown );\n        int  Unknown5( out                                            int              unknown );\n        int  Unknown6( int                                                             unknown );\n        int  Unknown7();\n        int  Unknown8( out int   unknown );\n        int  Unknown9( int       unknown );\n        int  Unknown10( int      unknownX, int unknownY );\n        int  Unknown11( int      unknown );\n        int  Unknown12( out Size size1 );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"1841C6D7-4F9D-42C0-AF41-8747538F10E5\" )]\n    public interface IApplicationViewCollection\n    {\n        int  GetViews( out         IObjectArray array );\n        int  GetViewsByZOrder( out IObjectArray array );\n        int  GetViewsByAppUserModelId( string   id,          out IObjectArray     array );\n        int  GetViewForHWnd( IntPtr             hWnd,        out IApplicationView view );\n        int  GetViewForApplication( object      application, out IApplicationView view );\n        int  GetViewForAppUserModelId( string   id,          out IApplicationView view );\n        int  GetViewInFocus( out IntPtr         view );\n        int  Unknown1( out       IntPtr         view );\n        void RefreshCollection();\n        int  RegisterForApplicationViewChanges( object listener, out int cookie );\n        int  UnregisterForApplicationViewChanges( int  cookie );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"FF72FFDD-BE7E-43FC-9C03-AD81681E88E4\" )]\n    public interface IVirtualDesktop\n    {\n        bool IsViewVisible( IApplicationView view );\n        Guid GetId();\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"F31574D6-B682-4CDC-BD56-1827860ABEC6\" )]\n    internal interface IVirtualDesktopManagerInternal\n    {\n        int             GetCount();\n        void            MoveViewToDesktop( IApplicationView   view, IVirtualDesktop desktop );\n        bool            CanViewMoveDesktops( IApplicationView view );\n        IVirtualDesktop GetCurrentDesktop();\n        void            GetDesktops( out IObjectArray desktops );\n\n        [PreserveSig]\n        int GetAdjacentDesktop( IVirtualDesktop from, int direction, out IVirtualDesktop desktop );\n\n        void            SwitchDesktop( IVirtualDesktop desktop );\n        IVirtualDesktop CreateDesktop();\n        void            RemoveDesktop( IVirtualDesktop desktop, IVirtualDesktop fallback );\n        IVirtualDesktop FindDesktop( ref Guid          desktopId );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"0F3A72B0-4566-487E-9A33-4ED302F6D6CE\" )]\n    internal interface IVirtualDesktopManagerInternal2\n    {\n        int             GetCount();\n        void            MoveViewToDesktop( IApplicationView   view, IVirtualDesktop desktop );\n        bool            CanViewMoveDesktops( IApplicationView view );\n        IVirtualDesktop GetCurrentDesktop();\n        void            GetDesktops( out IObjectArray desktops );\n\n        [PreserveSig]\n        int GetAdjacentDesktop( IVirtualDesktop from, int direction, out IVirtualDesktop desktop );\n\n        void            SwitchDesktop( IVirtualDesktop desktop );\n        IVirtualDesktop CreateDesktop();\n        void            RemoveDesktop( IVirtualDesktop desktop, IVirtualDesktop fallback );\n        IVirtualDesktop FindDesktop( ref Guid          desktopId );\n        void            Unknown1( IVirtualDesktop      desktop, out IntPtr unknown1, out IntPtr unknown2 );\n#if NET5_0_OR_GREATER\n        void SetName( IVirtualDesktop desktop, IntPtr newName );\n#else\n        void SetName( IVirtualDesktop desktop, [MarshalAs( UnmanagedType.HString )] string name );\n#endif\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"A5CD92FF-29BE-454C-8D04-D82879FB3F1B\" )]\n    internal interface IVirtualDesktopManager\n    {\n        bool IsWindowOnCurrentVirtualDesktop( IntPtr topLevelWindow );\n        Guid GetWindowDesktopId( IntPtr              topLevelWindow );\n        void MoveWindowToDesktop( IntPtr             topLevelWindow, ref Guid desktopId );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"4CE81583-1E4C-4632-A621-07A53543148F\" )]\n    internal interface IVirtualDesktopPinnedApps\n    {\n        bool IsAppIdPinned( string          appId );\n        void PinAppID( string               appId );\n        void UnpinAppID( string             appId );\n        bool IsViewPinned( IApplicationView applicationView );\n        void PinView( IApplicationView      applicationView );\n        void UnpinView( IApplicationView    applicationView );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"92CA9DCD-5622-4BBA-A805-5E9F541BD8C9\" )]\n    public interface IObjectArray\n    {\n        void GetCount( out int count );\n        void GetAt( int        index, ref Guid iid, [MarshalAs( UnmanagedType.Interface )] out object obj );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"6D5140C1-7436-11CE-8034-00AA006009FA\" )]\n    internal interface IServiceProvider10\n    {\n        [return: MarshalAs( UnmanagedType.IUnknown )]\n        object QueryService( ref Guid service, ref Guid riid );\n    }\n\n    [ComImport]\n    [Guid( \"C179334C-4295-40D3-BEA1-C654D965605A\" )]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    public interface IVirtualDesktopNotification\n    {\n        void VirtualDesktopCreated( IVirtualDesktop pDesktop );\n\n        void VirtualDesktopDestroyBegin( IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback );\n\n        void VirtualDesktopDestroyFailed( IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback );\n\n        void VirtualDesktopDestroyed( IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback );\n\n        void ViewVirtualDesktopChanged( IApplicationView pView );\n\n        void CurrentVirtualDesktopChanged( IVirtualDesktop pDesktopOld, IVirtualDesktop pDesktopNew );\n    }\n\n    [ComImport]\n    [Guid( \"0CD45E71-D927-4F15-8B0A-8FEF525337BF\" )]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    public interface IVirtualDesktopNotificationService\n    {\n        uint Register( IVirtualDesktopNotification pNotification );\n\n        void Unregister( uint dwCookie );\n    }\n}"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop10/VirtualDesktop.cs",
    "content": "// Author: Markus Scholtes, 2021\n// Version 1.9, 2021-10-08\n// Version for Windows 10 1809 to 21H1\n// Compile with:\n// C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\csc.exe VirtualDesktop.cs\n// Based on http://stackoverflow.com/a/32417530, Windows 10 SDK, github project Grabacr07/VirtualDesktop and own research\n\n/////////////////////////////////////////////////\n// Dylan Cheng (https://github.com/newlooper)\n// added Notifications about desktop\n// added conditional compile for C#/WinRT breaking change on .NET 5.0+\n\nusing System;\nusing System.Diagnostics;\nusing System.Runtime.InteropServices;\nusing Microsoft.Win32;\nusing VirtualSpace;\n#if NET5_0_OR_GREATER\nusing WinRT;\n#endif\n\nnamespace VirtualDesktop\n{\n    public class Desktop : IDesktop\n    {\n        private readonly IVirtualDesktop _ivd;\n\n        private Desktop( IVirtualDesktop desktop )\n        {\n            _ivd = desktop;\n        }\n\n        public Guid Guid => _ivd.GetId();\n\n        public static int Count =>\n            // return the number of desktops\n            DesktopManager.GetDesktopCount();\n\n        public static Desktop Current\n        {\n            get\n            {\n                // returns current desktop\n                try\n                {\n                    return new Desktop( DesktopManager.VirtualDesktopManagerInternal.GetCurrentDesktop() );\n                }\n                catch\n                {\n                    DesktopManager.ResetDesktopManager();\n                    return new Desktop( DesktopManager.VirtualDesktopManagerInternal.GetCurrentDesktop() );\n                }\n            }\n        }\n\n        public bool IsVisible =>\n            // return true if this desktop is the current displayed one\n            ReferenceEquals( _ivd, DesktopManager.VirtualDesktopManagerInternal.GetCurrentDesktop() );\n\n        public Desktop Left\n        {\n            // return desktop at the left of this one, null if none\n            get\n            {\n                var hr = DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 3, out var desktop ); // 3 = LeftDirection\n                if ( hr == 0 )\n                    return new Desktop( desktop );\n                else\n                    return null;\n            }\n        }\n\n        public Desktop Right\n        {\n            // return desktop at the right of this one, null if none\n            get\n            {\n                var hr = DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 4, out var desktop ); // 4 = RightDirection\n                if ( hr == 0 )\n                    return new Desktop( desktop );\n                else\n                    return null;\n            }\n        }\n\n        // get process id to window handle\n        [DllImport( \"user32.dll\" )]\n        private static extern int GetWindowThreadProcessId( IntPtr hWnd, out int lpdwProcessId );\n\n        // get handle of active window\n        [DllImport( \"user32.dll\" )]\n        private static extern IntPtr GetForegroundWindow();\n\n        public override int GetHashCode()\n        {\n            // get hash\n            return _ivd.GetHashCode();\n        }\n\n        public override bool Equals( object? obj )\n        {\n            // compare with object\n            return obj is Desktop desk && ReferenceEquals( _ivd, desk._ivd );\n        }\n\n        public static Desktop FromIndex( int index )\n        {\n            // return desktop object from index (-> index = 0..Count-1)\n            return new Desktop( DesktopManager.GetDesktop( index ) );\n        }\n\n        public static Desktop? FromWindow( IntPtr hWnd )\n        {\n            // return desktop object to desktop on which window <hWnd> is displayed\n            if ( hWnd == IntPtr.Zero ) return null;\n            var id = DesktopManager.VirtualDesktopManager.GetWindowDesktopId( hWnd );\n            return new Desktop( DesktopManager.VirtualDesktopManagerInternal.FindDesktop( ref id ) );\n        }\n\n        public static int SysIndexFromDesktop( Desktop desktop )\n        {\n            // return index of desktop object or -1 if not found\n            if ( desktop == null ) return -1;\n            return DesktopManager.GetDesktopIndex( desktop._ivd );\n        }\n\n        public static string DesktopNameFromDesktop( Desktop desktop )\n        {\n            // return name of desktop or \"Desktop n\" if it has no name\n            var guid = desktop._ivd.GetId();\n\n            // read desktop name in registry\n            string desktopName = null;\n            try\n            {\n                desktopName = (string)Registry.GetValue(\n                    \"HKEY_CURRENT_USER\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Explorer\\\\VirtualDesktops\\\\Desktops\\\\{\" + guid.ToString() + \"}\", \"Name\",\n                    null );\n            }\n            catch\n            {\n            }\n\n            // no name found, generate generic name\n            if ( string.IsNullOrEmpty( desktopName ) )\n            {\n                // create name \"Desktop n\" (n = number starting with 1)\n                desktopName = \"Desktop \" + ( DesktopManager.GetDesktopIndex( desktop._ivd ) + 1 ).ToString();\n            }\n\n            return desktopName;\n        }\n\n        public static string DesktopNameFromIndex( int index )\n        {\n            // return name of desktop from index (-> index = 0..Count-1) or \"Desktop n\" if it has no name\n            var guid = DesktopManager.GetDesktop( index ).GetId();\n\n            // read desktop name in registry\n            string desktopName = null;\n            try\n            {\n                desktopName = (string)Registry.GetValue(\n                    \"HKEY_CURRENT_USER\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Explorer\\\\VirtualDesktops\\\\Desktops\\\\{\" + guid.ToString() + \"}\", \"Name\",\n                    null );\n            }\n            catch\n            {\n            }\n\n            // no name found, generate generic name\n            if ( string.IsNullOrEmpty( desktopName ) )\n            {\n                // create name \"Desktop n\" (n = number starting with 1)\n                desktopName = \"Desktop \" + ( index + 1 ).ToString();\n            }\n\n            return desktopName;\n        }\n\n        public static bool HasDesktopNameFromIndex( int index )\n        {\n            // return true is desktop is named or false if it has no name\n            var guid = DesktopManager.GetDesktop( index ).GetId();\n\n            // read desktop name in registry\n            string desktopName = null;\n            try\n            {\n                desktopName = (string)Registry.GetValue(\n                    \"HKEY_CURRENT_USER\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Explorer\\\\VirtualDesktops\\\\Desktops\\\\{\" + guid.ToString() + \"}\", \"Name\",\n                    null );\n            }\n            catch\n            {\n            }\n\n            // name found?\n            if ( string.IsNullOrEmpty( desktopName ) )\n                return false;\n            else\n                return true;\n        }\n\n        public static int SearchDesktop( string partialName )\n        {\n            // get index of desktop with partial name, return -1 if no desktop found\n            var index = -1;\n\n            for ( var i = 0; i < DesktopManager.GetDesktopCount(); i++ )\n            {\n                // loop through all virtual desktops and compare partial name to desktop name\n                if ( DesktopNameFromIndex( i ).ToUpper().IndexOf( partialName.ToUpper() ) >= 0 )\n                {\n                    index = i;\n                    break;\n                }\n            }\n\n            return index;\n        }\n\n        public static Desktop Create()\n        {\n            // create a new desktop\n            return new Desktop( DesktopManager.VirtualDesktopManagerInternal.CreateDesktop() );\n        }\n\n        public void Remove( Desktop? fallback = null )\n        {\n            // destroy desktop and switch to <fallback>\n            IVirtualDesktop fallbackDesktop;\n            if ( fallback == null )\n            {\n                // if no fallback is given use desktop to the left except for desktop 0.\n                var dtToCheck = new Desktop( DesktopManager.GetDesktop( 0 ) );\n                if ( Equals( dtToCheck ) )\n                {\n                    // desktop 0: set fallback to second desktop (= \"right\" desktop)\n                    DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 4, out fallbackDesktop ); // 4 = RightDirection\n                }\n                else\n                {\n                    // set fallback to \"left\" desktop\n                    DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 3, out fallbackDesktop ); // 3 = LeftDirection\n                }\n            }\n            else\n                // set fallback desktop\n                fallbackDesktop = fallback._ivd;\n\n            DesktopManager.VirtualDesktopManagerInternal.RemoveDesktop( _ivd, fallbackDesktop );\n        }\n\n        public void SetName( string name )\n        {\n            // set name for desktop, empty string removes name\n            if ( DesktopManager.VirtualDesktopManagerInternal2 != null ) // only if interface to set name is present\n            {\n#if NET5_0_OR_GREATER\n                var newName = MarshalString.CreateMarshaler( name );\n                DesktopManager.VirtualDesktopManagerInternal2.SetName( _ivd, MarshalString.GetAbi( newName ) );\n#else\n                DesktopManager.VirtualDesktopManagerInternal2.SetName( _ivd, name );\n#endif\n            }\n        }\n\n        public void MakeVisible()\n        {\n            // make this desktop visible\n            DesktopManager.VirtualDesktopManagerInternal.SwitchDesktop( _ivd );\n        }\n\n        public void MoveWindow( IntPtr hWnd )\n        {\n            // move window to this desktop\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            _ = GetWindowThreadProcessId( hWnd, out var processId );\n\n            if ( Process.GetCurrentProcess().Id == processId )\n            {\n                // window of process\n                try // the easy way (if we are owner)\n                {\n                    DesktopManager.VirtualDesktopManager.MoveWindowToDesktop( hWnd, _ivd.GetId() );\n                }\n                catch // window of process, but we are not the owner\n                {\n                    DesktopManager.ApplicationViewCollection.GetViewForHWnd( hWnd, out var view );\n                    DesktopManager.VirtualDesktopManagerInternal.MoveViewToDesktop( view, _ivd );\n                }\n            }\n            else\n            {\n                // window of other process\n                DesktopManager.ApplicationViewCollection.GetViewForHWnd( hWnd, out var view );\n                try\n                {\n                    DesktopManager.VirtualDesktopManagerInternal.MoveViewToDesktop( view, _ivd );\n                }\n                catch\n                {\n                    // could not move active window, try main window (or whatever windows thinks is the main window)\n                    DesktopManager.ApplicationViewCollection.GetViewForHWnd(\n                        Process.GetProcessById( processId ).MainWindowHandle,\n                        out view );\n                    DesktopManager.VirtualDesktopManagerInternal.MoveViewToDesktop( view, _ivd );\n                }\n            }\n        }\n\n        public void MoveActiveWindow()\n        {\n            // move active window to this desktop\n            MoveWindow( GetForegroundWindow() );\n        }\n\n        public bool HasWindow( IntPtr hWnd )\n        {\n            // return true if window is on this desktop\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            return _ivd.GetId() == DesktopManager.VirtualDesktopManager.GetWindowDesktopId( hWnd );\n        }\n\n        public static bool IsWindowPinned( IntPtr hWnd )\n        {\n            // return true if window is pinned to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            return DesktopManager.VirtualDesktopPinnedApps.IsViewPinned( hWnd.GetApplicationView() );\n        }\n\n        public static void PinWindow( IntPtr hWnd )\n        {\n            // pin window to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var view = hWnd.GetApplicationView();\n            if ( !DesktopManager.VirtualDesktopPinnedApps.IsViewPinned( view ) )\n            {\n                // pin only if not already pinned\n                DesktopManager.VirtualDesktopPinnedApps.PinView( view );\n            }\n        }\n\n        public static void UnpinWindow( IntPtr hWnd )\n        {\n            // unpin window from all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var view = hWnd.GetApplicationView();\n            if ( DesktopManager.VirtualDesktopPinnedApps.IsViewPinned( view ) )\n            {\n                // unpin only if not already unpinned\n                DesktopManager.VirtualDesktopPinnedApps.UnpinView( view );\n            }\n        }\n\n        public static bool IsApplicationPinned( IntPtr hWnd )\n        {\n            // return true if application for window is pinned to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            return DesktopManager.VirtualDesktopPinnedApps.IsAppIdPinned( DesktopManager.GetAppId( hWnd ) );\n        }\n\n        public static void PinApplication( IntPtr hWnd )\n        {\n            // pin application for window to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var appId = DesktopManager.GetAppId( hWnd );\n            if ( !DesktopManager.VirtualDesktopPinnedApps.IsAppIdPinned( appId ) )\n            {\n                // pin only if not already pinned\n                DesktopManager.VirtualDesktopPinnedApps.PinAppID( appId );\n            }\n        }\n\n        public static void UnpinApplication( IntPtr hWnd )\n        {\n            // unpin application for window from all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var view  = hWnd.GetApplicationView();\n            var appId = DesktopManager.GetAppId( hWnd );\n            if ( DesktopManager.VirtualDesktopPinnedApps.IsAppIdPinned( appId ) )\n            {\n                // unpin only if pinned\n                DesktopManager.VirtualDesktopPinnedApps.UnpinAppID( appId );\n            }\n        }\n\n        public static Desktop? FromId( Guid guid )\n        {\n            try\n            {\n                return new Desktop( DesktopManager.VirtualDesktopManagerInternal.FindDesktop( ref guid ) );\n            }\n            catch\n            {\n                return null;\n            }\n        }\n    }\n}"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop10/VirtualDesktop10.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFrameworks>net6.0-windows</TargetFrameworks>\n        <Nullable>enable</Nullable>\n        <CsWinRTEnabled>false</CsWinRTEnabled>\n        <LangVersion>9</LangVersion>\n    </PropertyGroup>\n\n    <ItemGroup Condition=\" '$(TargetFramework)' == 'net5.0-windows' Or '$(TargetFramework)' == 'net6.0-windows' \">\n        <PackageReference Include=\"Microsoft.Windows.CsWinRT\" Version=\"1.4.1\" />\n    </ItemGroup>\n\n    <ItemGroup>\n        <ProjectReference Include=\"..\\..\\Bridge\\Bridge.csproj\" />\n    </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop10/VirtualDesktopManager.cs",
    "content": "﻿// Author: Markus Scholtes, 2021\n// Version 1.9, 2021-10-08\n// Version for Windows 10 1809 to 21H1\n// Compile with:\n// C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\csc.exe VirtualDesktop.cs\n// Based on http://stackoverflow.com/a/32417530, Windows 10 SDK, github project Grabacr07/VirtualDesktop and own research\n\n/////////////////////////////////////////////////\n// Dylan Cheng (https://github.com/newlooper)\n// added Notifications about desktop\n// added conditional compile for C#/WinRT breaking change on .NET 5.0+\n\nusing System;\nusing System.Runtime.InteropServices;\n#if NET5_0_OR_GREATER\nusing WinRT;\n#endif\n\nnamespace VirtualDesktop\n{\n    public static class DesktopManager\n    {\n        private static  DisposableNotification             _disposableNotification;\n        private static  IVirtualDesktopNotificationService VirtualDesktopNotificationService;\n        internal static IVirtualDesktopManagerInternal     VirtualDesktopManagerInternal;\n        internal static IVirtualDesktopManagerInternal2    VirtualDesktopManagerInternal2;\n        internal static IVirtualDesktopManager             VirtualDesktopManager;\n        internal static IVirtualDesktopPinnedApps          VirtualDesktopPinnedApps;\n        public static   IApplicationViewCollection         ApplicationViewCollection;\n\n        static DesktopManager()\n        {\n            if ( Environment.OSVersion.Version is {Major: 10, Build: < 22000} )\n                Init();\n        }\n\n        public static void ResetDesktopManager()\n        {\n            Init();\n        }\n\n        private static void Init()\n        {\n            var shell = (IServiceProvider10)Activator.CreateInstance( Type.GetTypeFromCLSID( Guids.CLSID_ImmersiveShell ) );\n\n            VirtualDesktopManager = (IVirtualDesktopManager)Activator.CreateInstance(\n                Type.GetTypeFromCLSID( Guids.CLSID_VirtualDesktopManager ) );\n\n            VirtualDesktopManagerInternal = (IVirtualDesktopManagerInternal)shell.QueryService(\n                Guids.CLSID_VirtualDesktopManagerInternal,\n                typeof( IVirtualDesktopManagerInternal ).GUID );\n            try\n            {\n                VirtualDesktopManagerInternal2 = (IVirtualDesktopManagerInternal2)shell.QueryService(\n                    Guids.CLSID_VirtualDesktopManagerInternal,\n                    typeof( IVirtualDesktopManagerInternal2 ).GUID );\n            }\n            catch\n            {\n                VirtualDesktopManagerInternal2 = null;\n            }\n\n            ApplicationViewCollection = (IApplicationViewCollection)shell.QueryService(\n                typeof( IApplicationViewCollection ).GUID,\n                typeof( IApplicationViewCollection ).GUID );\n            VirtualDesktopPinnedApps = (IVirtualDesktopPinnedApps)shell.QueryService(\n                Guids.CLSID_VirtualDesktopPinnedApps,\n                typeof( IVirtualDesktopPinnedApps ).GUID );\n            VirtualDesktopNotificationService = (IVirtualDesktopNotificationService)shell.QueryService(\n                Guids.CLSID_VirtualDesktopNotificationService,\n                typeof( IVirtualDesktopNotificationService ).GUID );\n\n            _disposableNotification = new DisposableNotification();\n            _disposableNotification.DwCookie = VirtualDesktopNotificationService.Register( new EventProxy() );\n        }\n\n        public static int GetDesktopCount()\n        {\n            try\n            {\n                return VirtualDesktopManagerInternal.GetCount();\n            }\n            catch\n            {\n                ResetDesktopManager();\n                return VirtualDesktopManagerInternal.GetCount();\n            }\n        }\n\n        public static IVirtualDesktop GetDesktop( int index )\n        {\n            // get desktop with index\n            var count = GetDesktopCount();\n            if ( index < 0 || index >= count ) throw new ArgumentOutOfRangeException( nameof( index ) );\n            VirtualDesktopManagerInternal.GetDesktops( out var desktops );\n            desktops.GetAt( index, typeof( IVirtualDesktop ).GUID, out var objDesktop );\n            Marshal.ReleaseComObject( desktops );\n            return (IVirtualDesktop)objDesktop;\n        }\n\n        internal static int GetDesktopIndex( IVirtualDesktop desktop )\n        {\n            // get index of desktop\n            var count    = GetDesktopCount();\n            var index    = -1;\n            var idSearch = desktop.GetId();\n            VirtualDesktopManagerInternal.GetDesktops( out var desktops );\n            for ( var i = 0; i < count; i++ )\n            {\n                desktops.GetAt( i, typeof( IVirtualDesktop ).GUID, out var objDesktop );\n                if ( idSearch.CompareTo( ( (IVirtualDesktop)objDesktop ).GetId() ) == 0 )\n                {\n                    index = i;\n                    break;\n                }\n            }\n\n            Marshal.ReleaseComObject( desktops );\n            return index;\n        }\n\n        internal static IApplicationView GetApplicationView( this IntPtr hWnd )\n        {\n            // get application view to window handle\n            ApplicationViewCollection.GetViewForHWnd( hWnd, out var view );\n            return view;\n        }\n\n        internal static string GetAppId( IntPtr hWnd )\n        {\n            // get Application ID to window handle\n            hWnd.GetApplicationView().GetAppUserModelId( out var appId );\n            return appId;\n        }\n\n        public static int GetViewCount()\n        {\n            ApplicationViewCollection.GetViews( out var objectArray );\n            objectArray.GetCount( out var count );\n            Marshal.ReleaseComObject( objectArray );\n            return count;\n        }\n\n        public static event EventHandler<IVirtualDesktop>?                Created;\n        public static event EventHandler<VirtualDesktopDestroyEventArgs>? DestroyBegin;\n        public static event EventHandler<VirtualDesktopDestroyEventArgs>? DestroyFailed;\n        public static event EventHandler<VirtualDesktopDestroyEventArgs>? Destroyed;\n        public static event EventHandler<VirtualDesktopChangedEventArgs>? CurrentChanged;\n\n        private class DisposableNotification : IDisposable\n        {\n            private bool _isDisposed;\n            public  uint DwCookie { private get; set; }\n\n            public void Dispose()\n            {\n                if ( _isDisposed ) return;\n\n                VirtualDesktopNotificationService.Unregister( DwCookie );\n                _isDisposed = true;\n            }\n        }\n\n        // public static event EventHandler<VirtualDesktopRenamedEventArgs>? Renamed;\n        // public static event EventHandler<VirtualDesktopWallpaperChangedEventArgs>? WallpaperChanged;\n\n        private class EventProxy : IVirtualDesktopNotification\n        {\n            public void VirtualDesktopCreated( IVirtualDesktop pDesktop )\n            {\n                Created?.Invoke( this, pDesktop );\n            }\n\n            public void VirtualDesktopDestroyBegin( IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback )\n            {\n                DestroyBegin?.Invoke( this, new VirtualDesktopDestroyEventArgs( pDesktopDestroyed, pDesktopFallback ) );\n            }\n\n            public void VirtualDesktopDestroyFailed( IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback )\n            {\n                DestroyFailed?.Invoke( this, new VirtualDesktopDestroyEventArgs( pDesktopDestroyed, pDesktopFallback ) );\n            }\n\n            public void VirtualDesktopDestroyed( IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback )\n            {\n                Destroyed?.Invoke( this, new VirtualDesktopDestroyEventArgs( pDesktopDestroyed, pDesktopFallback ) );\n            }\n\n            public void ViewVirtualDesktopChanged( IApplicationView pView )\n            {\n                // throw new NotImplementedException();\n            }\n\n            public void CurrentVirtualDesktopChanged( IVirtualDesktop pDesktopOld, IVirtualDesktop pDesktopNew )\n            {\n                CurrentChanged?.Invoke( this, new VirtualDesktopChangedEventArgs( pDesktopOld, pDesktopNew ) );\n            }\n\n            // public void VirtualDesktopRenamed( IVirtualDesktop pDesktop, string chName )\n            // {\n            //     Renamed?.Invoke( this, new VirtualDesktopRenamedEventArgs( pDesktop, chName ) );\n            // }\n        }\n    }\n\n    public class VirtualDesktopRenamedEventArgs : EventArgs\n    {\n        public VirtualDesktopRenamedEventArgs( IVirtualDesktop desktop, string name )\n        {\n            Desktop = desktop;\n            Name = name;\n        }\n\n        public IVirtualDesktop Desktop { get; }\n        public string          Name    { get; }\n    }\n\n    // public class VirtualDesktopWallpaperChangedEventArgs : EventArgs\n    // {\n    //     public VirtualDesktopWallpaperChangedEventArgs( IVirtualDesktop desktop, string path )\n    //     {\n    //         Desktop = desktop;\n    //         Path = path;\n    //     }\n    //\n    //     public IVirtualDesktop Desktop { get; }\n    //     public string          Path    { get; }\n    // }\n\n    public class VirtualDesktopChangedEventArgs : EventArgs\n    {\n        public VirtualDesktopChangedEventArgs( IVirtualDesktop oldDesktop, IVirtualDesktop newDesktop )\n        {\n            OldDesktop = oldDesktop;\n            NewDesktop = newDesktop;\n        }\n\n        public IVirtualDesktop OldDesktop { get; }\n        public IVirtualDesktop NewDesktop { get; }\n    }\n\n    // public class VirtualDesktopMovedEventArgs : EventArgs\n    // {\n    //     public VirtualDesktopMovedEventArgs( IVirtualDesktop desktop, int oldIndex, int newIndex )\n    //     {\n    //         Desktop = desktop;\n    //         OldIndex = oldIndex;\n    //         NewIndex = newIndex;\n    //     }\n    //\n    //     public IVirtualDesktop Desktop  { get; }\n    //     public int             OldIndex { get; }\n    //     public int             NewIndex { get; }\n    // }\n\n    public class VirtualDesktopDestroyEventArgs : EventArgs\n    {\n        public VirtualDesktopDestroyEventArgs( IVirtualDesktop destroyed, IVirtualDesktop fallback )\n        {\n            Destroyed = destroyed;\n            Fallback = fallback;\n        }\n\n        public IVirtualDesktop Destroyed { get; }\n        public IVirtualDesktop Fallback  { get; }\n    }\n}"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop11/COM.cs",
    "content": "﻿// Author: Markus Scholtes, 2021\n// Version 1.9, 2021-10-08\n// Version for Windows 10 21H2 and Windows 11\n// Compile with:\n// C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\csc.exe VirtualDesktop11.cs\n// Based on http://stackoverflow.com/a/32417530, Windows 10 SDK, github project Grabacr07/VirtualDesktop and own research\n\n/////////////////////////////////////////////////\n// Dylan Cheng (https://github.com/newlooper)\n// added Notifications about desktop\n// added conditional compile for C#/WinRT breaking change on .NET 5.0+\n\nusing System;\nusing System.Runtime.InteropServices;\n\nnamespace VirtualDesktop\n{\n    internal static class Guids\n    {\n        public static readonly Guid CLSID_ImmersiveShell                    = new( \"C2F03A33-21F5-47FA-B4BB-156362A2F239\" );\n        public static readonly Guid CLSID_VirtualDesktopManagerInternal     = new( \"C5E0CDCA-7B6E-41B2-9FC4-D93975CC467B\" );\n        public static readonly Guid CLSID_VirtualDesktopManager             = new( \"AA509086-5CA9-4C25-8F95-589D3C07B48A\" );\n        public static readonly Guid CLSID_VirtualDesktopPinnedApps          = new( \"B5A399E7-1C87-46B8-88E9-FC5747B171BD\" );\n        public static readonly Guid CLSID_VirtualDesktopNotificationService = new( \"A501FDEC-4A09-464C-AE4E-1B9C21B84918\" );\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct Size\n    {\n        public int X;\n        public int Y;\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct Rect\n    {\n        public int Left;\n        public int Top;\n        public int Right;\n        public int Bottom;\n    }\n\n    public enum APPLICATION_VIEW_CLOAK_TYPE : int\n    {\n        AVCT_NONE            = 0,\n        AVCT_DEFAULT         = 1,\n        AVCT_VIRTUAL_DESKTOP = 2\n    }\n\n    public enum APPLICATION_VIEW_COMPATIBILITY_POLICY : int\n    {\n        AVCP_NONE                = 0,\n        AVCP_SMALL_SCREEN        = 1,\n        AVCP_TABLET_SMALL_SCREEN = 2,\n        AVCP_VERY_SMALL_SCREEN   = 3,\n        AVCP_HIGH_SCALE_FACTOR   = 4\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"372E1D3B-38D3-42E4-A15B-8AB2B178F513\" )]\n    public interface IApplicationView\n    {\n        void GetIIdsSlot();\n        void GetRuntimeClassNameSlot();\n        void GetTrustLevelSlot();\n        int  SetFocus();\n        int  SwitchTo();\n        int  TryInvokeBack( IntPtr /* IAsyncCallback* */ callback );\n        int  GetThumbnailWindow( out IntPtr hWnd );\n        int  GetMonitor( out         IntPtr /* IImmersiveMonitor */ immersiveMonitor );\n        int  GetVisibility( out      int visibility );\n        int  SetCloak( APPLICATION_VIEW_CLOAK_TYPE cloakType, int unknown );\n        int  GetPosition( ref Guid guid /* GUID for IApplicationViewPosition */, out IntPtr /* IApplicationViewPosition** */ position );\n        int  SetPosition( ref IntPtr /* IApplicationViewPosition* */ position );\n        int  InsertAfterWindow( IntPtr hWnd );\n        int  GetExtendedFramePosition( out                              Rect rect );\n        int  GetAppUserModelId( [MarshalAs( UnmanagedType.LPWStr )] out string id );\n        int  SetAppUserModelId( string id );\n        int  IsEqualByAppUserModelId( string id, out int result );\n        int  GetViewState( out uint state );\n        int  SetViewState( uint state );\n        int  GetNeediness( out               int neediness );\n        int  GetLastActivationTimestamp( out ulong timestamp );\n        int  SetLastActivationTimestamp( ulong timestamp );\n        int  GetVirtualDesktopId( out Guid guid );\n        int  SetVirtualDesktopId( ref Guid guid );\n        int  GetShowInSwitchers( out  int flag );\n        int  SetShowInSwitchers( int flag );\n        int  GetScaleFactor( out             int factor );\n        int  CanReceiveInput( out            bool canReceiveInput );\n        int  GetCompatibilityPolicyType( out APPLICATION_VIEW_COMPATIBILITY_POLICY flags );\n        int  SetCompatibilityPolicyType( APPLICATION_VIEW_COMPATIBILITY_POLICY flags );\n        int  GetSizeConstraints( IntPtr /* IImmersiveMonitor* */ monitor, out Size size1, out Size size2 );\n        int  GetSizeConstraintsForDpi( uint uint1, out Size size1, out Size size2 );\n        int  SetSizeConstraintsForDpi( ref uint uint1, ref Size size1, ref Size size2 );\n        int  OnMinSizePreferencesUpdated( IntPtr hWnd );\n        int  ApplyOperation( IntPtr /* IApplicationViewOperation* */ operation );\n        int  IsTray( out                  bool isTray );\n        int  IsInHighZOrderBand( out      bool isInHighZOrderBand );\n        int  IsSplashScreenPresented( out bool isSplashScreenPresented );\n        int  Flash();\n        int  GetRootSwitchableOwner( out                              IApplicationView rootSwitchableOwner );\n        int  EnumerateOwnershipTree( out                              IObjectArray     ownershipTree );\n        int  GetEnterpriseId( [MarshalAs( UnmanagedType.LPWStr )] out string           enterpriseId );\n        int  IsMirrored( out                                          bool             isMirrored );\n        int  Unknown1( out                                            int              unknown );\n        int  Unknown2( out                                            int              unknown );\n        int  Unknown3( out                                            int              unknown );\n        int  Unknown4( out                                            int              unknown );\n        int  Unknown5( out                                            int              unknown );\n        int  Unknown6( int                                                             unknown );\n        int  Unknown7();\n        int  Unknown8( out int   unknown );\n        int  Unknown9( int       unknown );\n        int  Unknown10( int      unknownX, int unknownY );\n        int  Unknown11( int      unknown );\n        int  Unknown12( out Size size1 );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"1841C6D7-4F9D-42C0-AF41-8747538F10E5\" )]\n    public interface IApplicationViewCollection\n    {\n        int  GetViews( out         IObjectArray array );\n        int  GetViewsByZOrder( out IObjectArray array );\n        int  GetViewsByAppUserModelId( string   id,          out IObjectArray     array );\n        int  GetViewForHWnd( IntPtr             hWnd,        out IApplicationView view );\n        int  GetViewForApplication( object      application, out IApplicationView view );\n        int  GetViewForAppUserModelId( string   id,          out IApplicationView view );\n        int  GetViewInFocus( out IntPtr         view );\n        int  Unknown1( out       IntPtr         view );\n        void RefreshCollection();\n        int  RegisterForApplicationViewChanges( object listener, out int cookie );\n        int  UnregisterForApplicationViewChanges( int  cookie );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"536D3495-B208-4CC9-AE26-DE8111275BF8\" )]\n    public interface IVirtualDesktop\n    {\n        bool   IsViewVisible( IApplicationView view );\n        Guid   GetId();\n        IntPtr Unknown1();\n\n#if NET5_0_OR_GREATER\n        public void GetString( out IntPtr hstr );\n#else\n        [return: MarshalAs( UnmanagedType.HString )]\n        string GetName();\n#endif\n\n        [return: MarshalAs( UnmanagedType.HString )]\n        string GetWallpaperPath();\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"B2F925B9-5A0F-4D2E-9F4D-2B1507593C10\" )]\n    internal interface IVirtualDesktopManagerInternal\n    {\n        int             GetCount( IntPtr                      hWndOrMon );\n        void            MoveViewToDesktop( IApplicationView   view, IVirtualDesktop desktop );\n        bool            CanViewMoveDesktops( IApplicationView view );\n        IVirtualDesktop GetCurrentDesktop( IntPtr             hWndOrMon );\n        IObjectArray    GetAllCurrentDesktops();\n        void            GetDesktops( IntPtr hWndOrMon, out IObjectArray desktops );\n\n        [PreserveSig]\n        int GetAdjacentDesktop( IVirtualDesktop from, int direction, out IVirtualDesktop desktop );\n\n        void            SwitchDesktop( IntPtr                                hWndOrMon, IVirtualDesktop desktop );\n        IVirtualDesktop CreateDesktop( IntPtr                                hWndOrMon );\n        void            MoveDesktop( IVirtualDesktop                         desktop, IntPtr          hWndOrMon, int nIndex );\n        void            RemoveDesktop( IVirtualDesktop                       desktop, IVirtualDesktop fallback );\n        IVirtualDesktop FindDesktop( ref Guid                                desktopId );\n        void            GetDesktopSwitchIncludeExcludeViews( IVirtualDesktop desktop, out IObjectArray unknown1, out IObjectArray unknown2 );\n#if NET5_0_OR_GREATER\n        void SetName( IVirtualDesktop      desktop, IntPtr newName );\n        void SetWallpaper( IVirtualDesktop desktop, IntPtr path );\n#else\n        void SetDesktopName( IVirtualDesktop      desktop, [MarshalAs( UnmanagedType.HString )] string name );\n        void SetDesktopWallpaper( IVirtualDesktop desktop, [MarshalAs( UnmanagedType.HString )] string path );\n#endif\n        void UpdateWallpaperPathForAllDesktops( [MarshalAs( UnmanagedType.HString )] string path );\n        void CopyDesktopState( IApplicationView                                             pView0, IApplicationView pView1 );\n        int  GetDesktopIsPerMonitor();\n        void SetDesktopIsPerMonitor( bool state );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"A5CD92FF-29BE-454C-8D04-D82879FB3F1B\" )]\n    internal interface IVirtualDesktopManager\n    {\n        bool IsWindowOnCurrentVirtualDesktop( IntPtr topLevelWindow );\n        Guid GetWindowDesktopId( IntPtr              topLevelWindow );\n        void MoveWindowToDesktop( IntPtr             topLevelWindow, ref Guid desktopId );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"4CE81583-1E4C-4632-A621-07A53543148F\" )]\n    internal interface IVirtualDesktopPinnedApps\n    {\n        bool IsAppIdPinned( string          appId );\n        void PinAppID( string               appId );\n        void UnpinAppID( string             appId );\n        bool IsViewPinned( IApplicationView applicationView );\n        void PinView( IApplicationView      applicationView );\n        void UnpinView( IApplicationView    applicationView );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"92CA9DCD-5622-4BBA-A805-5E9F541BD8C9\" )]\n    public interface IObjectArray\n    {\n        void GetCount( out int count );\n        void GetAt( int        index, ref Guid iid, [MarshalAs( UnmanagedType.Interface )] out object obj );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"6D5140C1-7436-11CE-8034-00AA006009FA\" )]\n    internal interface IServiceProvider10\n    {\n        [return: MarshalAs( UnmanagedType.IUnknown )]\n        object QueryService( ref Guid service, ref Guid riid );\n    }\n\n    [ComImport]\n    [Guid( \"cd403e52-deed-4c13-b437-b98380f2b1e8\" )]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    public interface IVirtualDesktopNotification\n    {\n        void VirtualDesktopCreated( IObjectArray       p0, IVirtualDesktop pDesktop );\n        void VirtualDesktopDestroyBegin( IObjectArray  p0, IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback );\n        void VirtualDesktopDestroyFailed( IObjectArray p0, IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback );\n        void VirtualDesktopDestroyed( IObjectArray     p0, IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback );\n        void Proc7( int                                p0 );\n        void VirtualDesktopMoved( IObjectArray         p0, IVirtualDesktop pDesktop, int nIndexFrom, int nIndexTo );\n#if NET5_0_OR_GREATER\n        void VirtualDesktopRenamed( IVirtualDesktop pDesktop, IntPtr newName );\n#else\n        void VirtualDesktopRenamed( IVirtualDesktop pDesktop, [MarshalAs( UnmanagedType.HString )] string chName );\n#endif\n        void ViewVirtualDesktopChanged( IApplicationView pView );\n        void CurrentVirtualDesktopChanged( IObjectArray  p0, IVirtualDesktop pDesktopOld, IVirtualDesktop pDesktopNew );\n\n#if NET5_0_OR_GREATER\n        void VirtualDesktopWallpaperChanged( IVirtualDesktop pDesktop, IntPtr newPath );\n#else\n        void VirtualDesktopWallpaperChanged( IVirtualDesktop pDesktop, [MarshalAs( UnmanagedType.HString )] string chPath );\n#endif\n    }\n\n    [ComImport]\n    [Guid( \"0cd45e71-d927-4f15-8b0a-8fef525337bf\" )]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    public interface IVirtualDesktopNotificationService\n    {\n        uint Register( IVirtualDesktopNotification pNotification );\n        void Unregister( uint                      dwCookie );\n    }\n}"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop11/VirtualDesktop.cs",
    "content": "// Author: Markus Scholtes, 2021\n// Version 1.9, 2021-10-08\n// Version for Windows 10 21H2 and Windows 11\n// Compile with:\n// C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\csc.exe VirtualDesktop11.cs\n// Based on http://stackoverflow.com/a/32417530, Windows 10 SDK, github project Grabacr07/VirtualDesktop and own research\n\n/////////////////////////////////////////////////\n// Dylan Cheng (https://github.com/newlooper)\n// added Notifications about desktop\n// added conditional compile for C#/WinRT breaking change on .NET 5.0+\n\nusing System;\nusing System.Diagnostics;\nusing System.Runtime.InteropServices;\nusing VirtualSpace;\n#if NET5_0_OR_GREATER\nusing WinRT;\n#endif\n\nnamespace VirtualDesktop\n{\n    public class Desktop: IDesktop\n    {\n        private readonly IVirtualDesktop _ivd;\n\n        private Desktop( IVirtualDesktop desktop )\n        {\n            _ivd = desktop;\n        }\n\n        public Guid Guid => _ivd.GetId();\n\n        public static int Count =>\n            // return the number of desktops\n            DesktopManager.GetDesktopCount();\n\n        public static Desktop Current\n        {\n            get\n            {\n                // returns current desktop\n                try\n                {\n                    return new Desktop( DesktopManager.VirtualDesktopManagerInternal.GetCurrentDesktop( IntPtr.Zero ) );\n                }\n                catch\n                {\n                    DesktopManager.ResetDesktopManager();\n                    return new Desktop( DesktopManager.VirtualDesktopManagerInternal.GetCurrentDesktop( IntPtr.Zero ) );\n                }\n            }\n        }\n\n        public bool IsVisible =>\n            // return true if this desktop is the current displayed one\n            ReferenceEquals( _ivd, DesktopManager.VirtualDesktopManagerInternal.GetCurrentDesktop( IntPtr.Zero ) );\n\n        public Desktop Left\n        {\n            // return desktop at the left of this one, null if none\n            get\n            {\n                var hr = DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 3, out var desktop ); // 3 = LeftDirection\n                if ( hr == 0 )\n                    return new Desktop( desktop );\n                else\n                    return null;\n            }\n        }\n\n        public Desktop Right\n        {\n            // return desktop at the right of this one, null if none\n            get\n            {\n                var hr = DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 4, out var desktop ); // 4 = RightDirection\n                if ( hr == 0 )\n                    return new Desktop( desktop );\n                else\n                    return null;\n            }\n        }\n\n        // get process id to window handle\n        [DllImport( \"user32.dll\" )]\n        private static extern int GetWindowThreadProcessId( IntPtr hWnd, out int lpdwProcessId );\n\n        // get handle of active window\n        [DllImport( \"user32.dll\" )]\n        private static extern IntPtr GetForegroundWindow();\n\n        public override int GetHashCode()\n        {\n            // get hash\n            return _ivd.GetHashCode();\n        }\n\n        public override bool Equals( object? obj )\n        {\n            // compare with object\n            return obj is Desktop desk && ReferenceEquals( _ivd, desk._ivd );\n        }\n\n        public static Desktop FromIndex( int index )\n        {\n            // return desktop object from index (-> index = 0..Count-1)\n            return new Desktop( DesktopManager.GetDesktop( index ) );\n        }\n\n        public static Desktop FromWindow( IntPtr hWnd )\n        {\n            // return desktop object to desktop on which window <hWnd> is displayed\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var id = DesktopManager.VirtualDesktopManager.GetWindowDesktopId( hWnd );\n            return new Desktop( DesktopManager.VirtualDesktopManagerInternal.FindDesktop( ref id ) );\n        }\n\n        public static int SysIndexFromDesktop( Desktop desktop )\n        {\n            // return index of desktop object or -1 if not found\n            if ( desktop == null ) return -1;\n            return DesktopManager.GetDesktopIndex( desktop._ivd );\n        }\n\n        public static string DesktopNameFromDesktop( Desktop desktop )\n        {\n            // return name of desktop or \"Desktop n\" if it has no name\n\n            // get desktop name\n            string desktopName = null;\n            try\n            {\n#if NET5_0_OR_GREATER\n                desktop._ivd.GetString( out var hstr );\n                desktopName = MarshalString.FromAbi( hstr );\n#else\n                desktopName = desktop._ivd.GetName();\n#endif\n            }\n            catch ( Exception )\n            {\n            }\n\n            // no name found, generate generic name\n            if ( string.IsNullOrEmpty( desktopName ) )\n            {\n                // create name \"Desktop n\" (n = number starting with 1)\n                desktopName = \"Desktop \" + ( DesktopManager.GetDesktopIndex( desktop._ivd ) + 1 ).ToString();\n            }\n\n            return desktopName;\n        }\n\n        public static string DesktopNameFromIndex( int index )\n        {\n            // return name of desktop from index (-> index = 0..Count-1) or \"Desktop n\" if it has no name\n\n            // get desktop name\n            string desktopName = null;\n            try\n            {\n#if NET5_0_OR_GREATER\n                DesktopManager.GetDesktop( index ).GetString( out var hstr );\n                desktopName = MarshalString.FromAbi( hstr );\n#else\n                desktopName = DesktopManager.GetDesktop( index ).GetName();\n#endif\n            }\n            catch\n            {\n            }\n\n            // no name found, generate generic name\n            if ( string.IsNullOrEmpty( desktopName ) )\n            {\n                // create name \"Desktop n\" (n = number starting with 1)\n                desktopName = \"Desktop \" + ( index + 1 ).ToString();\n            }\n\n            return desktopName;\n        }\n\n        public static bool HasDesktopNameFromIndex( int index )\n        {\n            // return true is desktop is named or false if it has no name\n\n            // read desktop name in registry\n            string desktopName = null;\n            try\n            {\n#if NET5_0_OR_GREATER\n                DesktopManager.GetDesktop( index ).GetString( out var hstr );\n                desktopName = MarshalString.FromAbi( hstr );\n#else\n                desktopName = DesktopManager.GetDesktop( index ).GetName();\n#endif\n            }\n            catch\n            {\n            }\n\n            // name found?\n            if ( string.IsNullOrEmpty( desktopName ) )\n                return false;\n            else\n                return true;\n        }\n\n        public static string DesktopWallpaperFromIndex( int index )\n        {\n            // return name of desktop wallpaper from index (-> index = 0..Count-1)\n\n            // get desktop name\n            var desktopWpPath = \"\";\n            try\n            {\n                desktopWpPath = DesktopManager.GetDesktop( index ).GetWallpaperPath();\n            }\n            catch\n            {\n            }\n\n            return desktopWpPath;\n        }\n\n        public static int SearchDesktop( string partialName )\n        {\n            // get index of desktop with partial name, return -1 if no desktop found\n            var index = -1;\n\n            for ( var i = 0; i < DesktopManager.GetDesktopCount(); i++ )\n            {\n                // loop through all virtual desktops and compare partial name to desktop name\n                if ( DesktopNameFromIndex( i ).ToUpper().IndexOf( partialName.ToUpper() ) >= 0 )\n                {\n                    index = i;\n                    break;\n                }\n            }\n\n            return index;\n        }\n\n        public static Desktop Create()\n        {\n            // create a new desktop\n            return new Desktop( DesktopManager.VirtualDesktopManagerInternal.CreateDesktop( IntPtr.Zero ) );\n        }\n\n        public void Remove( Desktop? fallback = null )\n        {\n            // destroy desktop and switch to <fallback>\n            IVirtualDesktop fallbackDesktop;\n            if ( fallback == null )\n            {\n                // if no fallback is given use desktop to the left except for desktop 0.\n                var dtToCheck = new Desktop( DesktopManager.GetDesktop( 0 ) );\n                if ( Equals( dtToCheck ) )\n                {\n                    // desktop 0: set fallback to second desktop (= \"right\" desktop)\n                    DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 4, out fallbackDesktop ); // 4 = RightDirection\n                }\n                else\n                {\n                    // set fallback to \"left\" desktop\n                    DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 3, out fallbackDesktop ); // 3 = LeftDirection\n                }\n            }\n            else\n                // set fallback desktop\n                fallbackDesktop = fallback._ivd;\n\n            DesktopManager.VirtualDesktopManagerInternal.RemoveDesktop( _ivd, fallbackDesktop );\n        }\n\n        public static void RemoveAll()\n        {\n            // remove all desktops but visible\n            DesktopManager.VirtualDesktopManagerInternal.SetDesktopIsPerMonitor( true );\n        }\n\n        public void Move( int index )\n        {\n            // move current desktop to desktop in index (-> index = 0..Count-1)\n            DesktopManager.VirtualDesktopManagerInternal.MoveDesktop( _ivd, IntPtr.Zero, index );\n        }\n\n        public void SetName( string name )\n        {\n            // set name for desktop, empty string removes name\n#if NET5_0_OR_GREATER\n            var newName = MarshalString.CreateMarshaler( name );\n            DesktopManager.VirtualDesktopManagerInternal.SetName( _ivd, MarshalString.GetAbi( newName ) );\n#else\n            DesktopManager.VirtualDesktopManagerInternal.SetDesktopName( _ivd, name );\n#endif\n        }\n\n        public void SetWallpaperPath( string path )\n        {\n            // set path for wallpaper, empty string removes path\n            if ( string.IsNullOrEmpty( path ) ) throw new ArgumentNullException();\n\n#if NET5_0_OR_GREATER\n            var newPath = MarshalString.CreateMarshaler( path );\n            DesktopManager.VirtualDesktopManagerInternal.SetWallpaper( _ivd, MarshalString.GetAbi( newPath ) );\n#else\n            DesktopManager.VirtualDesktopManagerInternal.SetDesktopWallpaper( _ivd, path );\n#endif\n        }\n\n        public static void SetAllWallpaperPaths( string path )\n        {\n            // set wallpaper path for all desktops\n            if ( string.IsNullOrEmpty( path ) ) throw new ArgumentNullException();\n            DesktopManager.VirtualDesktopManagerInternal.UpdateWallpaperPathForAllDesktops( path );\n        }\n\n        public void MakeVisible()\n        {\n            // make this desktop visible\n            DesktopManager.VirtualDesktopManagerInternal.SwitchDesktop( IntPtr.Zero, _ivd );\n        }\n\n        public void MoveWindow( IntPtr hWnd )\n        {\n            // move window to this desktop\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            _ = GetWindowThreadProcessId( hWnd, out var processId );\n\n            if ( Process.GetCurrentProcess().Id == processId )\n            {\n                // window of process\n                try // the easy way (if we are owner)\n                {\n                    DesktopManager.VirtualDesktopManager.MoveWindowToDesktop( hWnd, _ivd.GetId() );\n                }\n                catch // window of process, but we are not the owner\n                {\n                    DesktopManager.ApplicationViewCollection.GetViewForHWnd( hWnd, out var view );\n                    DesktopManager.VirtualDesktopManagerInternal.MoveViewToDesktop( view, _ivd );\n                }\n            }\n            else\n            {\n                // window of other process\n                DesktopManager.ApplicationViewCollection.GetViewForHWnd( hWnd, out var view );\n                try\n                {\n                    DesktopManager.VirtualDesktopManagerInternal.MoveViewToDesktop( view, _ivd );\n                }\n                catch\n                {\n                    // could not move active window, try main window (or whatever windows thinks is the main window)\n                    DesktopManager.ApplicationViewCollection.GetViewForHWnd(\n                        Process.GetProcessById( processId ).MainWindowHandle,\n                        out view );\n                    DesktopManager.VirtualDesktopManagerInternal.MoveViewToDesktop( view, _ivd );\n                }\n            }\n        }\n\n        public void MoveActiveWindow()\n        {\n            // move active window to this desktop\n            MoveWindow( GetForegroundWindow() );\n        }\n\n        public bool HasWindow( IntPtr hWnd )\n        {\n            // return true if window is on this desktop\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            return _ivd.GetId() == DesktopManager.VirtualDesktopManager.GetWindowDesktopId( hWnd );\n        }\n\n        public static bool IsWindowPinned( IntPtr hWnd )\n        {\n            // return true if window is pinned to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            return DesktopManager.VirtualDesktopPinnedApps.IsViewPinned( hWnd.GetApplicationView() );\n        }\n\n        public static void PinWindow( IntPtr hWnd )\n        {\n            // pin window to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var view = hWnd.GetApplicationView();\n            if ( !DesktopManager.VirtualDesktopPinnedApps.IsViewPinned( view ) )\n            {\n                // pin only if not already pinned\n                DesktopManager.VirtualDesktopPinnedApps.PinView( view );\n            }\n        }\n\n        public static void UnpinWindow( IntPtr hWnd )\n        {\n            // unpin window from all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var view = hWnd.GetApplicationView();\n            if ( DesktopManager.VirtualDesktopPinnedApps.IsViewPinned( view ) )\n            {\n                // unpin only if not already unpinned\n                DesktopManager.VirtualDesktopPinnedApps.UnpinView( view );\n            }\n        }\n\n        public static bool IsApplicationPinned( IntPtr hWnd )\n        {\n            // return true if application for window is pinned to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            return DesktopManager.VirtualDesktopPinnedApps.IsAppIdPinned( DesktopManager.GetAppId( hWnd ) );\n        }\n\n        public static void PinApplication( IntPtr hWnd )\n        {\n            // pin application for window to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var appId = DesktopManager.GetAppId( hWnd );\n            if ( !DesktopManager.VirtualDesktopPinnedApps.IsAppIdPinned( appId ) )\n            {\n                // pin only if not already pinned\n                DesktopManager.VirtualDesktopPinnedApps.PinAppID( appId );\n            }\n        }\n\n        public static void UnpinApplication( IntPtr hWnd )\n        {\n            // unpin application for window from all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var view  = hWnd.GetApplicationView();\n            var appId = DesktopManager.GetAppId( hWnd );\n            if ( DesktopManager.VirtualDesktopPinnedApps.IsAppIdPinned( appId ) )\n            {\n                // unpin only if pinned\n                DesktopManager.VirtualDesktopPinnedApps.UnpinAppID( appId );\n            }\n        }\n\n        public static Desktop? FromId( Guid guid )\n        {\n            try\n            {\n                return new Desktop( DesktopManager.VirtualDesktopManagerInternal.FindDesktop( ref guid ) );\n            }\n            catch\n            {\n                return null;\n            }\n        }\n    }\n}"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop11/VirtualDesktop11.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFrameworks>net6.0-windows</TargetFrameworks>\n        <Nullable>enable</Nullable>\n        <CsWinRTEnabled>false</CsWinRTEnabled>\n        <LangVersion>9</LangVersion>\n    </PropertyGroup>\n\n    <ItemGroup Condition=\" '$(TargetFramework)' == 'net5.0-windows' Or '$(TargetFramework)' == 'net6.0-windows' \">\n        <PackageReference Include=\"Microsoft.Windows.CsWinRT\" Version=\"1.4.1\" />\n    </ItemGroup>\n\n    <ItemGroup>\n        <ProjectReference Include=\"..\\..\\Bridge\\Bridge.csproj\" />\n    </ItemGroup>\n\n</Project>"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop11/VirtualDesktopManager.cs",
    "content": "﻿// Author: Markus Scholtes, 2021\n// Version 1.9, 2021-10-08\n// Version for Windows 10 21H2 and Windows 11\n// Compile with:\n// C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\csc.exe VirtualDesktop11.cs\n// Based on http://stackoverflow.com/a/32417530, Windows 10 SDK, github project Grabacr07/VirtualDesktop and own research\n\n/////////////////////////////////////////////////\n// Dylan Cheng (https://github.com/newlooper)\n// added Notifications about desktop\n// added conditional compile for C#/WinRT breaking change on .NET 5.0+\n\nusing System;\nusing System.Runtime.InteropServices;\n#if NET5_0_OR_GREATER\nusing WinRT;\n#endif\n\nnamespace VirtualDesktop\n{\n    public static class DesktopManager\n    {\n        private static  DisposableNotification             _disposableNotification;\n        private static  IVirtualDesktopNotificationService VirtualDesktopNotificationService;\n        internal static IVirtualDesktopManagerInternal     VirtualDesktopManagerInternal;\n        internal static IVirtualDesktopManager             VirtualDesktopManager;\n        internal static IVirtualDesktopPinnedApps          VirtualDesktopPinnedApps;\n        public static   IApplicationViewCollection         ApplicationViewCollection;\n\n        static DesktopManager()\n        {\n            if ( Environment.OSVersion.Version is {Major: 10, Build: >= 22000} )\n                Init();\n        }\n\n        public static void ResetDesktopManager()\n        {\n            Init();\n        }\n\n        private static void Init()\n        {\n            var shell = (IServiceProvider10)Activator.CreateInstance( Type.GetTypeFromCLSID( Guids.CLSID_ImmersiveShell ) );\n\n            VirtualDesktopManager = (IVirtualDesktopManager)Activator.CreateInstance(\n                Type.GetTypeFromCLSID( Guids.CLSID_VirtualDesktopManager ) );\n\n            VirtualDesktopManagerInternal = (IVirtualDesktopManagerInternal)shell.QueryService(\n                Guids.CLSID_VirtualDesktopManagerInternal,\n                typeof( IVirtualDesktopManagerInternal ).GUID );\n            ApplicationViewCollection = (IApplicationViewCollection)shell.QueryService(\n                typeof( IApplicationViewCollection ).GUID,\n                typeof( IApplicationViewCollection ).GUID );\n            VirtualDesktopPinnedApps = (IVirtualDesktopPinnedApps)shell.QueryService(\n                Guids.CLSID_VirtualDesktopPinnedApps,\n                typeof( IVirtualDesktopPinnedApps ).GUID );\n            VirtualDesktopNotificationService = (IVirtualDesktopNotificationService)shell.QueryService(\n                Guids.CLSID_VirtualDesktopNotificationService,\n                typeof( IVirtualDesktopNotificationService ).GUID );\n\n            _disposableNotification = new DisposableNotification();\n            _disposableNotification.DwCookie = VirtualDesktopNotificationService.Register( new EventProxy() );\n        }\n\n        public static int GetDesktopCount()\n        {\n            try\n            {\n                return VirtualDesktopManagerInternal.GetCount( IntPtr.Zero );\n            }\n            catch\n            {\n                ResetDesktopManager();\n                return VirtualDesktopManagerInternal.GetCount( IntPtr.Zero );\n            }\n        }\n\n        public static IVirtualDesktop GetDesktop( int index )\n        {\n            // get desktop with index\n            var count = GetDesktopCount();\n            if ( index < 0 || index >= count ) throw new ArgumentOutOfRangeException( nameof( index ) );\n            VirtualDesktopManagerInternal.GetDesktops( IntPtr.Zero, out var desktops );\n            desktops.GetAt( index, typeof( IVirtualDesktop ).GUID, out var objDesktop );\n            Marshal.ReleaseComObject( desktops );\n            return (IVirtualDesktop)objDesktop;\n        }\n\n        internal static int GetDesktopIndex( IVirtualDesktop desktop )\n        {\n            // get index of desktop\n            var count    = GetDesktopCount();\n            var index    = -1;\n            var idSearch = desktop.GetId();\n            VirtualDesktopManagerInternal.GetDesktops( IntPtr.Zero, out var desktops );\n            for ( var i = 0; i < count; i++ )\n            {\n                desktops.GetAt( i, typeof( IVirtualDesktop ).GUID, out var objDesktop );\n                if ( idSearch.CompareTo( ( (IVirtualDesktop)objDesktop ).GetId() ) == 0 )\n                {\n                    index = i;\n                    break;\n                }\n            }\n\n            Marshal.ReleaseComObject( desktops );\n            return index;\n        }\n\n        internal static IApplicationView GetApplicationView( this IntPtr hWnd )\n        {\n            // get application view to window handle\n            ApplicationViewCollection.GetViewForHWnd( hWnd, out var view );\n            return view;\n        }\n\n        internal static string GetAppId( IntPtr hWnd )\n        {\n            // get Application ID to window handle\n            hWnd.GetApplicationView().GetAppUserModelId( out var appId );\n            return appId;\n        }\n\n        public static int GetViewCount()\n        {\n            ApplicationViewCollection.GetViews( out var objectArray );\n            objectArray.GetCount( out var count );\n            Marshal.ReleaseComObject( objectArray );\n            return count;\n        }\n\n        public static event EventHandler<IVirtualDesktop>?                         Created;\n        public static event EventHandler<VirtualDesktopDestroyEventArgs>?          DestroyBegin;\n        public static event EventHandler<VirtualDesktopDestroyEventArgs>?          DestroyFailed;\n        public static event EventHandler<VirtualDesktopDestroyEventArgs>?          Destroyed;\n        public static event EventHandler<VirtualDesktopChangedEventArgs>?          CurrentChanged;\n        public static event EventHandler<VirtualDesktopMovedEventArgs>?            Moved;\n        public static event EventHandler<VirtualDesktopRenamedEventArgs>?          Renamed;\n        public static event EventHandler<VirtualDesktopWallpaperChangedEventArgs>? WallpaperChanged;\n\n        private class DisposableNotification : IDisposable\n        {\n            private bool _isDisposed;\n            public  uint DwCookie { private get; set; }\n\n            public void Dispose()\n            {\n                if ( _isDisposed ) return;\n\n                VirtualDesktopNotificationService.Unregister( DwCookie );\n                _isDisposed = true;\n            }\n        }\n\n        private class EventProxy : IVirtualDesktopNotification\n        {\n            public void ViewVirtualDesktopChanged( IApplicationView pView )\n            {\n                // throw new NotImplementedException();\n            }\n\n            public void CurrentVirtualDesktopChanged( IObjectArray p0, IVirtualDesktop pDesktopOld, IVirtualDesktop pDesktopNew )\n            {\n                CurrentChanged?.Invoke( this, new VirtualDesktopChangedEventArgs( pDesktopOld, pDesktopNew ) );\n            }\n\n            public void VirtualDesktopCreated( IObjectArray p0, IVirtualDesktop pDesktop )\n            {\n                Created?.Invoke( this, pDesktop );\n            }\n\n            public void VirtualDesktopDestroyBegin( IObjectArray p0, IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback )\n            {\n                DestroyBegin?.Invoke( this, new VirtualDesktopDestroyEventArgs( pDesktopDestroyed, pDesktopFallback ) );\n            }\n\n            public void VirtualDesktopDestroyFailed( IObjectArray p0, IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback )\n            {\n                DestroyFailed?.Invoke( this, new VirtualDesktopDestroyEventArgs( pDesktopDestroyed, pDesktopFallback ) );\n            }\n\n            public void VirtualDesktopDestroyed( IObjectArray p0, IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback )\n            {\n                Destroyed?.Invoke( this, new VirtualDesktopDestroyEventArgs( pDesktopDestroyed, pDesktopFallback ) );\n            }\n\n            public void Proc7( int p0 )\n            {\n                // throw new NotImplementedException();\n            }\n\n            public void VirtualDesktopMoved( IObjectArray p0, IVirtualDesktop pDesktop, int nIndexFrom, int nIndexTo )\n            {\n                Moved?.Invoke( this, new VirtualDesktopMovedEventArgs( pDesktop, nIndexFrom, nIndexTo ) );\n            }\n\n#if NET5_0_OR_GREATER\n            public void VirtualDesktopRenamed( IVirtualDesktop pDesktop, IntPtr newName )\n            {\n                var name = MarshalString.FromAbi( newName );\n                Renamed?.Invoke( this, new VirtualDesktopRenamedEventArgs( pDesktop, name ) );\n            }\n#else\n            public void VirtualDesktopRenamed( IVirtualDesktop pDesktop, string chName )\n            {\n                Renamed?.Invoke( this, new VirtualDesktopRenamedEventArgs( pDesktop, chName ) );\n            }\n#endif\n\n#if NET5_0_OR_GREATER\n            public void VirtualDesktopWallpaperChanged( IVirtualDesktop pDesktop, IntPtr newPath )\n            {\n                var path = MarshalString.FromAbi( newPath );\n                WallpaperChanged?.Invoke( this, new VirtualDesktopWallpaperChangedEventArgs( pDesktop, path ) );\n            }\n#else\n            public void VirtualDesktopWallpaperChanged( IVirtualDesktop pDesktop, string chPath )\n            {\n                WallpaperChanged?.Invoke( this, new VirtualDesktopWallpaperChangedEventArgs( pDesktop, chPath ) );\n            }\n#endif\n        }\n    }\n\n    public class VirtualDesktopRenamedEventArgs : EventArgs\n    {\n        public VirtualDesktopRenamedEventArgs( IVirtualDesktop desktop, string name )\n        {\n            Desktop = desktop;\n            Name = name;\n        }\n\n        public IVirtualDesktop Desktop { get; }\n        public string          Name    { get; }\n    }\n\n    public class VirtualDesktopWallpaperChangedEventArgs : EventArgs\n    {\n        public VirtualDesktopWallpaperChangedEventArgs( IVirtualDesktop desktop, string path )\n        {\n            Desktop = desktop;\n            Path = path;\n        }\n\n        public IVirtualDesktop Desktop { get; }\n        public string          Path    { get; }\n    }\n\n\n    public class VirtualDesktopChangedEventArgs : EventArgs\n    {\n        public VirtualDesktopChangedEventArgs( IVirtualDesktop oldDesktop, IVirtualDesktop newDesktop )\n        {\n            OldDesktop = oldDesktop;\n            NewDesktop = newDesktop;\n        }\n\n        public IVirtualDesktop OldDesktop { get; }\n        public IVirtualDesktop NewDesktop { get; }\n    }\n\n    public class VirtualDesktopMovedEventArgs : EventArgs\n    {\n        public VirtualDesktopMovedEventArgs( IVirtualDesktop desktop, int oldIndex, int newIndex )\n        {\n            Desktop = desktop;\n            OldIndex = oldIndex;\n            NewIndex = newIndex;\n        }\n\n        public IVirtualDesktop Desktop  { get; }\n        public int             OldIndex { get; }\n        public int             NewIndex { get; }\n    }\n\n    public class VirtualDesktopDestroyEventArgs : EventArgs\n    {\n        public VirtualDesktopDestroyEventArgs( IVirtualDesktop destroyed, IVirtualDesktop fallback )\n        {\n            Destroyed = destroyed;\n            Fallback = fallback;\n        }\n\n        public IVirtualDesktop Destroyed { get; }\n        public IVirtualDesktop Fallback  { get; }\n    }\n}"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop11_21H2/COM.cs",
    "content": "﻿// Author: Markus Scholtes, 2021\n// Version 1.9, 2021-10-08\n// Version for Windows 10 21H2 and Windows 11\n// Compile with:\n// C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\csc.exe VirtualDesktop11.cs\n// Based on http://stackoverflow.com/a/32417530, Windows 10 SDK, github project Grabacr07/VirtualDesktop and own research\n\n/////////////////////////////////////////////////\n// Dylan Cheng (https://github.com/newlooper)\n// added Notifications about desktop\n// added conditional compile for C#/WinRT breaking change on .NET 5.0+\n\nusing System;\nusing System.Runtime.InteropServices;\n\nnamespace VirtualDesktop\n{\n    internal static class Guids\n    {\n        public static readonly Guid CLSID_ImmersiveShell                    = new( \"C2F03A33-21F5-47FA-B4BB-156362A2F239\" );\n        public static readonly Guid CLSID_VirtualDesktopManagerInternal     = new( \"C5E0CDCA-7B6E-41B2-9FC4-D93975CC467B\" );\n        public static readonly Guid CLSID_VirtualDesktopManager             = new( \"AA509086-5CA9-4C25-8F95-589D3C07B48A\" );\n        public static readonly Guid CLSID_VirtualDesktopPinnedApps          = new( \"B5A399E7-1C87-46B8-88E9-FC5747B171BD\" );\n        public static readonly Guid CLSID_VirtualDesktopNotificationService = new( \"A501FDEC-4A09-464C-AE4E-1B9C21B84918\" );\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct Size\n    {\n        public int X;\n        public int Y;\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct Rect\n    {\n        public int Left;\n        public int Top;\n        public int Right;\n        public int Bottom;\n    }\n\n    public enum APPLICATION_VIEW_CLOAK_TYPE : int\n    {\n        AVCT_NONE            = 0,\n        AVCT_DEFAULT         = 1,\n        AVCT_VIRTUAL_DESKTOP = 2\n    }\n\n    public enum APPLICATION_VIEW_COMPATIBILITY_POLICY : int\n    {\n        AVCP_NONE                = 0,\n        AVCP_SMALL_SCREEN        = 1,\n        AVCP_TABLET_SMALL_SCREEN = 2,\n        AVCP_VERY_SMALL_SCREEN   = 3,\n        AVCP_HIGH_SCALE_FACTOR   = 4\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"372E1D3B-38D3-42E4-A15B-8AB2B178F513\" )]\n    public interface IApplicationView\n    {\n        void GetIIdsSlot();\n        void GetRuntimeClassNameSlot();\n        void GetTrustLevelSlot();\n        int  SetFocus();\n        int  SwitchTo();\n        int  TryInvokeBack( IntPtr /* IAsyncCallback* */ callback );\n        int  GetThumbnailWindow( out IntPtr hWnd );\n        int  GetMonitor( out         IntPtr /* IImmersiveMonitor */ immersiveMonitor );\n        int  GetVisibility( out      int visibility );\n        int  SetCloak( APPLICATION_VIEW_CLOAK_TYPE cloakType, int unknown );\n        int  GetPosition( ref Guid guid /* GUID for IApplicationViewPosition */, out IntPtr /* IApplicationViewPosition** */ position );\n        int  SetPosition( ref IntPtr /* IApplicationViewPosition* */ position );\n        int  InsertAfterWindow( IntPtr hWnd );\n        int  GetExtendedFramePosition( out                              Rect rect );\n        int  GetAppUserModelId( [MarshalAs( UnmanagedType.LPWStr )] out string id );\n        int  SetAppUserModelId( string id );\n        int  IsEqualByAppUserModelId( string id, out int result );\n        int  GetViewState( out uint state );\n        int  SetViewState( uint state );\n        int  GetNeediness( out               int neediness );\n        int  GetLastActivationTimestamp( out ulong timestamp );\n        int  SetLastActivationTimestamp( ulong timestamp );\n        int  GetVirtualDesktopId( out Guid guid );\n        int  SetVirtualDesktopId( ref Guid guid );\n        int  GetShowInSwitchers( out  int flag );\n        int  SetShowInSwitchers( int flag );\n        int  GetScaleFactor( out             int factor );\n        int  CanReceiveInput( out            bool canReceiveInput );\n        int  GetCompatibilityPolicyType( out APPLICATION_VIEW_COMPATIBILITY_POLICY flags );\n        int  SetCompatibilityPolicyType( APPLICATION_VIEW_COMPATIBILITY_POLICY flags );\n        int  GetSizeConstraints( IntPtr /* IImmersiveMonitor* */ monitor, out Size size1, out Size size2 );\n        int  GetSizeConstraintsForDpi( uint uint1, out Size size1, out Size size2 );\n        int  SetSizeConstraintsForDpi( ref uint uint1, ref Size size1, ref Size size2 );\n        int  OnMinSizePreferencesUpdated( IntPtr hWnd );\n        int  ApplyOperation( IntPtr /* IApplicationViewOperation* */ operation );\n        int  IsTray( out                  bool isTray );\n        int  IsInHighZOrderBand( out      bool isInHighZOrderBand );\n        int  IsSplashScreenPresented( out bool isSplashScreenPresented );\n        int  Flash();\n        int  GetRootSwitchableOwner( out                              IApplicationView rootSwitchableOwner );\n        int  EnumerateOwnershipTree( out                              IObjectArray     ownershipTree );\n        int  GetEnterpriseId( [MarshalAs( UnmanagedType.LPWStr )] out string           enterpriseId );\n        int  IsMirrored( out                                          bool             isMirrored );\n        int  Unknown1( out                                            int              unknown );\n        int  Unknown2( out                                            int              unknown );\n        int  Unknown3( out                                            int              unknown );\n        int  Unknown4( out                                            int              unknown );\n        int  Unknown5( out                                            int              unknown );\n        int  Unknown6( int                                                             unknown );\n        int  Unknown7();\n        int  Unknown8( out int   unknown );\n        int  Unknown9( int       unknown );\n        int  Unknown10( int      unknownX, int unknownY );\n        int  Unknown11( int      unknown );\n        int  Unknown12( out Size size1 );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"1841C6D7-4F9D-42C0-AF41-8747538F10E5\" )]\n    public interface IApplicationViewCollection\n    {\n        int  GetViews( out         IObjectArray array );\n        int  GetViewsByZOrder( out IObjectArray array );\n        int  GetViewsByAppUserModelId( string   id,          out IObjectArray     array );\n        int  GetViewForHWnd( IntPtr             hWnd,        out IApplicationView view );\n        int  GetViewForApplication( object      application, out IApplicationView view );\n        int  GetViewForAppUserModelId( string   id,          out IApplicationView view );\n        int  GetViewInFocus( out IntPtr         view );\n        int  Unknown1( out       IntPtr         view );\n        void RefreshCollection();\n        int  RegisterForApplicationViewChanges( object listener, out int cookie );\n        int  UnregisterForApplicationViewChanges( int  cookie );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"536D3495-B208-4CC9-AE26-DE8111275BF8\" )]\n    public interface IVirtualDesktop\n    {\n        bool   IsViewVisible( IApplicationView view );\n        Guid   GetId();\n        IntPtr Unknown1();\n\n#if NET5_0_OR_GREATER\n        public void GetString( out IntPtr hstr );\n#else\n        [return: MarshalAs( UnmanagedType.HString )]\n        string GetName();\n#endif\n\n        [return: MarshalAs( UnmanagedType.HString )]\n        string GetWallpaperPath();\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"B2F925B9-5A0F-4D2E-9F4D-2B1507593C10\" )]\n    internal interface IVirtualDesktopManagerInternal\n    {\n        int             GetCount( IntPtr                      hWndOrMon );\n        void            MoveViewToDesktop( IApplicationView   view, IVirtualDesktop desktop );\n        bool            CanViewMoveDesktops( IApplicationView view );\n        IVirtualDesktop GetCurrentDesktop( IntPtr             hWndOrMon );\n        void            GetDesktops( IntPtr                   hWndOrMon, out IObjectArray desktops );\n\n        [PreserveSig]\n        int GetAdjacentDesktop( IVirtualDesktop from, int direction, out IVirtualDesktop desktop );\n\n        void            SwitchDesktop( IntPtr                                hWndOrMon, IVirtualDesktop desktop );\n        IVirtualDesktop CreateDesktop( IntPtr                                hWndOrMon );\n        void            MoveDesktop( IVirtualDesktop                         desktop, IntPtr          hWndOrMon, int nIndex );\n        void            RemoveDesktop( IVirtualDesktop                       desktop, IVirtualDesktop fallback );\n        IVirtualDesktop FindDesktop( ref Guid                                desktopId );\n        void            GetDesktopSwitchIncludeExcludeViews( IVirtualDesktop desktop, out IObjectArray unknown1, out IObjectArray unknown2 );\n#if NET5_0_OR_GREATER\n        void SetName( IVirtualDesktop      desktop, IntPtr newName );\n        void SetWallpaper( IVirtualDesktop desktop, IntPtr path );\n#else\n        void SetDesktopName( IVirtualDesktop      desktop, [MarshalAs( UnmanagedType.HString )] string name );\n        void SetDesktopWallpaper( IVirtualDesktop desktop, [MarshalAs( UnmanagedType.HString )] string path );\n#endif\n        void UpdateWallpaperPathForAllDesktops( [MarshalAs( UnmanagedType.HString )] string path );\n        void CopyDesktopState( IApplicationView                                             pView0, IApplicationView pView1 );\n        int  GetDesktopIsPerMonitor();\n        void SetDesktopIsPerMonitor( bool state );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"A5CD92FF-29BE-454C-8D04-D82879FB3F1B\" )]\n    internal interface IVirtualDesktopManager\n    {\n        bool IsWindowOnCurrentVirtualDesktop( IntPtr topLevelWindow );\n        Guid GetWindowDesktopId( IntPtr              topLevelWindow );\n        void MoveWindowToDesktop( IntPtr             topLevelWindow, ref Guid desktopId );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"4CE81583-1E4C-4632-A621-07A53543148F\" )]\n    internal interface IVirtualDesktopPinnedApps\n    {\n        bool IsAppIdPinned( string          appId );\n        void PinAppID( string               appId );\n        void UnpinAppID( string             appId );\n        bool IsViewPinned( IApplicationView applicationView );\n        void PinView( IApplicationView      applicationView );\n        void UnpinView( IApplicationView    applicationView );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"92CA9DCD-5622-4BBA-A805-5E9F541BD8C9\" )]\n    public interface IObjectArray\n    {\n        void GetCount( out int count );\n        void GetAt( int        index, ref Guid iid, [MarshalAs( UnmanagedType.Interface )] out object obj );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"6D5140C1-7436-11CE-8034-00AA006009FA\" )]\n    internal interface IServiceProvider10\n    {\n        [return: MarshalAs( UnmanagedType.IUnknown )]\n        object QueryService( ref Guid service, ref Guid riid );\n    }\n\n    [ComImport]\n    [Guid( \"cd403e52-deed-4c13-b437-b98380f2b1e8\" )]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    public interface IVirtualDesktopNotification\n    {\n        void VirtualDesktopCreated( IObjectArray       p0, IVirtualDesktop pDesktop );\n        void VirtualDesktopDestroyBegin( IObjectArray  p0, IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback );\n        void VirtualDesktopDestroyFailed( IObjectArray p0, IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback );\n        void VirtualDesktopDestroyed( IObjectArray     p0, IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback );\n        void Proc7( int                                p0 );\n        void VirtualDesktopMoved( IObjectArray         p0, IVirtualDesktop pDesktop, int nIndexFrom, int nIndexTo );\n#if NET5_0_OR_GREATER\n        void VirtualDesktopRenamed( IVirtualDesktop pDesktop, IntPtr newName );\n#else\n        void VirtualDesktopRenamed( IVirtualDesktop pDesktop, [MarshalAs( UnmanagedType.HString )] string chName );\n#endif\n        void ViewVirtualDesktopChanged( IApplicationView pView );\n        void CurrentVirtualDesktopChanged( IObjectArray  p0, IVirtualDesktop pDesktopOld, IVirtualDesktop pDesktopNew );\n\n#if NET5_0_OR_GREATER\n        void VirtualDesktopWallpaperChanged( IVirtualDesktop pDesktop, IntPtr newPath );\n#else\n        void VirtualDesktopWallpaperChanged( IVirtualDesktop pDesktop, [MarshalAs( UnmanagedType.HString )] string chPath );\n#endif\n    }\n\n    [ComImport]\n    [Guid( \"0cd45e71-d927-4f15-8b0a-8fef525337bf\" )]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    public interface IVirtualDesktopNotificationService\n    {\n        uint Register( IVirtualDesktopNotification pNotification );\n        void Unregister( uint                      dwCookie );\n    }\n}"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop11_21H2/VirtualDesktop.cs",
    "content": "// Author: Markus Scholtes, 2021\n// Version 1.9, 2021-10-08\n// Version for Windows 10 21H2 and Windows 11\n// Compile with:\n// C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\csc.exe VirtualDesktop11.cs\n// Based on http://stackoverflow.com/a/32417530, Windows 10 SDK, github project Grabacr07/VirtualDesktop and own research\n\n/////////////////////////////////////////////////\n// Dylan Cheng (https://github.com/newlooper)\n// added Notifications about desktop\n// added conditional compile for C#/WinRT breaking change on .NET 5.0+\n\nusing System;\nusing System.Diagnostics;\nusing System.Runtime.InteropServices;\nusing VirtualSpace;\n#if NET5_0_OR_GREATER\nusing WinRT;\n#endif\n\nnamespace VirtualDesktop\n{\n    public class Desktop: IDesktop\n    {\n        private readonly IVirtualDesktop _ivd;\n\n        private Desktop( IVirtualDesktop desktop )\n        {\n            _ivd = desktop;\n        }\n\n        public Guid Guid => _ivd.GetId();\n\n        public static int Count =>\n            // return the number of desktops\n            DesktopManager.GetDesktopCount();\n\n        public static Desktop Current\n        {\n            get\n            {\n                // returns current desktop\n                try\n                {\n                    return new Desktop( DesktopManager.VirtualDesktopManagerInternal.GetCurrentDesktop( IntPtr.Zero ) );\n                }\n                catch\n                {\n                    DesktopManager.ResetDesktopManager();\n                    return new Desktop( DesktopManager.VirtualDesktopManagerInternal.GetCurrentDesktop( IntPtr.Zero ) );\n                }\n            }\n        }\n\n        public bool IsVisible =>\n            // return true if this desktop is the current displayed one\n            ReferenceEquals( _ivd, DesktopManager.VirtualDesktopManagerInternal.GetCurrentDesktop( IntPtr.Zero ) );\n\n        public Desktop Left\n        {\n            // return desktop at the left of this one, null if none\n            get\n            {\n                var hr = DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 3, out var desktop ); // 3 = LeftDirection\n                if ( hr == 0 )\n                    return new Desktop( desktop );\n                else\n                    return null;\n            }\n        }\n\n        public Desktop Right\n        {\n            // return desktop at the right of this one, null if none\n            get\n            {\n                var hr = DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 4, out var desktop ); // 4 = RightDirection\n                if ( hr == 0 )\n                    return new Desktop( desktop );\n                else\n                    return null;\n            }\n        }\n\n        // get process id to window handle\n        [DllImport( \"user32.dll\" )]\n        private static extern int GetWindowThreadProcessId( IntPtr hWnd, out int lpdwProcessId );\n\n        // get handle of active window\n        [DllImport( \"user32.dll\" )]\n        private static extern IntPtr GetForegroundWindow();\n\n        public override int GetHashCode()\n        {\n            // get hash\n            return _ivd.GetHashCode();\n        }\n\n        public override bool Equals( object? obj )\n        {\n            // compare with object\n            return obj is Desktop desk && ReferenceEquals( _ivd, desk._ivd );\n        }\n\n        public static Desktop FromIndex( int index )\n        {\n            // return desktop object from index (-> index = 0..Count-1)\n            return new Desktop( DesktopManager.GetDesktop( index ) );\n        }\n\n        public static Desktop FromWindow( IntPtr hWnd )\n        {\n            // return desktop object to desktop on which window <hWnd> is displayed\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var id = DesktopManager.VirtualDesktopManager.GetWindowDesktopId( hWnd );\n            return new Desktop( DesktopManager.VirtualDesktopManagerInternal.FindDesktop( ref id ) );\n        }\n\n        public static int SysIndexFromDesktop( Desktop desktop )\n        {\n            // return index of desktop object or -1 if not found\n            if ( desktop == null ) return -1;\n            return DesktopManager.GetDesktopIndex( desktop._ivd );\n        }\n\n        public static string DesktopNameFromDesktop( Desktop desktop )\n        {\n            // return name of desktop or \"Desktop n\" if it has no name\n\n            // get desktop name\n            string desktopName = null;\n            try\n            {\n#if NET5_0_OR_GREATER\n                desktop._ivd.GetString( out var hstr );\n                desktopName = MarshalString.FromAbi( hstr );\n#else\n                desktopName = desktop._ivd.GetName();\n#endif\n            }\n            catch ( Exception )\n            {\n            }\n\n            // no name found, generate generic name\n            if ( string.IsNullOrEmpty( desktopName ) )\n            {\n                // create name \"Desktop n\" (n = number starting with 1)\n                desktopName = \"Desktop \" + ( DesktopManager.GetDesktopIndex( desktop._ivd ) + 1 ).ToString();\n            }\n\n            return desktopName;\n        }\n\n        public static string DesktopNameFromIndex( int index )\n        {\n            // return name of desktop from index (-> index = 0..Count-1) or \"Desktop n\" if it has no name\n\n            // get desktop name\n            string desktopName = null;\n            try\n            {\n#if NET5_0_OR_GREATER\n                DesktopManager.GetDesktop( index ).GetString( out var hstr );\n                desktopName = MarshalString.FromAbi( hstr );\n#else\n                desktopName = DesktopManager.GetDesktop( index ).GetName();\n#endif\n            }\n            catch\n            {\n            }\n\n            // no name found, generate generic name\n            if ( string.IsNullOrEmpty( desktopName ) )\n            {\n                // create name \"Desktop n\" (n = number starting with 1)\n                desktopName = \"Desktop \" + ( index + 1 ).ToString();\n            }\n\n            return desktopName;\n        }\n\n        public static bool HasDesktopNameFromIndex( int index )\n        {\n            // return true is desktop is named or false if it has no name\n\n            // read desktop name in registry\n            string desktopName = null;\n            try\n            {\n#if NET5_0_OR_GREATER\n                DesktopManager.GetDesktop( index ).GetString( out var hstr );\n                desktopName = MarshalString.FromAbi( hstr );\n#else\n                desktopName = DesktopManager.GetDesktop( index ).GetName();\n#endif\n            }\n            catch\n            {\n            }\n\n            // name found?\n            if ( string.IsNullOrEmpty( desktopName ) )\n                return false;\n            else\n                return true;\n        }\n\n        public static string DesktopWallpaperFromIndex( int index )\n        {\n            // return name of desktop wallpaper from index (-> index = 0..Count-1)\n\n            // get desktop name\n            var desktopWpPath = \"\";\n            try\n            {\n                desktopWpPath = DesktopManager.GetDesktop( index ).GetWallpaperPath();\n            }\n            catch\n            {\n            }\n\n            return desktopWpPath;\n        }\n\n        public static int SearchDesktop( string partialName )\n        {\n            // get index of desktop with partial name, return -1 if no desktop found\n            var index = -1;\n\n            for ( var i = 0; i < DesktopManager.GetDesktopCount(); i++ )\n            {\n                // loop through all virtual desktops and compare partial name to desktop name\n                if ( DesktopNameFromIndex( i ).ToUpper().IndexOf( partialName.ToUpper() ) >= 0 )\n                {\n                    index = i;\n                    break;\n                }\n            }\n\n            return index;\n        }\n\n        public static Desktop Create()\n        {\n            // create a new desktop\n            return new Desktop( DesktopManager.VirtualDesktopManagerInternal.CreateDesktop( IntPtr.Zero ) );\n        }\n\n        public void Remove( Desktop? fallback = null )\n        {\n            // destroy desktop and switch to <fallback>\n            IVirtualDesktop fallbackDesktop;\n            if ( fallback == null )\n            {\n                // if no fallback is given use desktop to the left except for desktop 0.\n                var dtToCheck = new Desktop( DesktopManager.GetDesktop( 0 ) );\n                if ( Equals( dtToCheck ) )\n                {\n                    // desktop 0: set fallback to second desktop (= \"right\" desktop)\n                    DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 4, out fallbackDesktop ); // 4 = RightDirection\n                }\n                else\n                {\n                    // set fallback to \"left\" desktop\n                    DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 3, out fallbackDesktop ); // 3 = LeftDirection\n                }\n            }\n            else\n                // set fallback desktop\n                fallbackDesktop = fallback._ivd;\n\n            DesktopManager.VirtualDesktopManagerInternal.RemoveDesktop( _ivd, fallbackDesktop );\n        }\n\n        public static void RemoveAll()\n        {\n            // remove all desktops but visible\n            DesktopManager.VirtualDesktopManagerInternal.SetDesktopIsPerMonitor( true );\n        }\n\n        public void Move( int index )\n        {\n            // move current desktop to desktop in index (-> index = 0..Count-1)\n            DesktopManager.VirtualDesktopManagerInternal.MoveDesktop( _ivd, IntPtr.Zero, index );\n        }\n\n        public void SetName( string name )\n        {\n            // set name for desktop, empty string removes name\n#if NET5_0_OR_GREATER\n            var newName = MarshalString.CreateMarshaler( name );\n            DesktopManager.VirtualDesktopManagerInternal.SetName( _ivd, MarshalString.GetAbi( newName ) );\n#else\n            DesktopManager.VirtualDesktopManagerInternal.SetDesktopName( _ivd, name );\n#endif\n        }\n\n        public void SetWallpaperPath( string path )\n        {\n            // set path for wallpaper, empty string removes path\n            if ( string.IsNullOrEmpty( path ) ) throw new ArgumentNullException();\n\n#if NET5_0_OR_GREATER\n            var newPath = MarshalString.CreateMarshaler( path );\n            DesktopManager.VirtualDesktopManagerInternal.SetWallpaper( _ivd, MarshalString.GetAbi( newPath ) );\n#else\n            DesktopManager.VirtualDesktopManagerInternal.SetDesktopWallpaper( _ivd, path );\n#endif\n        }\n\n        public static void SetAllWallpaperPaths( string path )\n        {\n            // set wallpaper path for all desktops\n            if ( string.IsNullOrEmpty( path ) ) throw new ArgumentNullException();\n            DesktopManager.VirtualDesktopManagerInternal.UpdateWallpaperPathForAllDesktops( path );\n        }\n\n        public void MakeVisible()\n        {\n            // make this desktop visible\n            DesktopManager.VirtualDesktopManagerInternal.SwitchDesktop( IntPtr.Zero, _ivd );\n        }\n\n        public void MoveWindow( IntPtr hWnd )\n        {\n            // move window to this desktop\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            _ = GetWindowThreadProcessId( hWnd, out var processId );\n\n            if ( Process.GetCurrentProcess().Id == processId )\n            {\n                // window of process\n                try // the easy way (if we are owner)\n                {\n                    DesktopManager.VirtualDesktopManager.MoveWindowToDesktop( hWnd, _ivd.GetId() );\n                }\n                catch // window of process, but we are not the owner\n                {\n                    DesktopManager.ApplicationViewCollection.GetViewForHWnd( hWnd, out var view );\n                    DesktopManager.VirtualDesktopManagerInternal.MoveViewToDesktop( view, _ivd );\n                }\n            }\n            else\n            {\n                // window of other process\n                DesktopManager.ApplicationViewCollection.GetViewForHWnd( hWnd, out var view );\n                try\n                {\n                    DesktopManager.VirtualDesktopManagerInternal.MoveViewToDesktop( view, _ivd );\n                }\n                catch\n                {\n                    // could not move active window, try main window (or whatever windows thinks is the main window)\n                    DesktopManager.ApplicationViewCollection.GetViewForHWnd(\n                        Process.GetProcessById( processId ).MainWindowHandle,\n                        out view );\n                    DesktopManager.VirtualDesktopManagerInternal.MoveViewToDesktop( view, _ivd );\n                }\n            }\n        }\n\n        public void MoveActiveWindow()\n        {\n            // move active window to this desktop\n            MoveWindow( GetForegroundWindow() );\n        }\n\n        public bool HasWindow( IntPtr hWnd )\n        {\n            // return true if window is on this desktop\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            return _ivd.GetId() == DesktopManager.VirtualDesktopManager.GetWindowDesktopId( hWnd );\n        }\n\n        public static bool IsWindowPinned( IntPtr hWnd )\n        {\n            // return true if window is pinned to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            return DesktopManager.VirtualDesktopPinnedApps.IsViewPinned( hWnd.GetApplicationView() );\n        }\n\n        public static void PinWindow( IntPtr hWnd )\n        {\n            // pin window to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var view = hWnd.GetApplicationView();\n            if ( !DesktopManager.VirtualDesktopPinnedApps.IsViewPinned( view ) )\n            {\n                // pin only if not already pinned\n                DesktopManager.VirtualDesktopPinnedApps.PinView( view );\n            }\n        }\n\n        public static void UnpinWindow( IntPtr hWnd )\n        {\n            // unpin window from all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var view = hWnd.GetApplicationView();\n            if ( DesktopManager.VirtualDesktopPinnedApps.IsViewPinned( view ) )\n            {\n                // unpin only if not already unpinned\n                DesktopManager.VirtualDesktopPinnedApps.UnpinView( view );\n            }\n        }\n\n        public static bool IsApplicationPinned( IntPtr hWnd )\n        {\n            // return true if application for window is pinned to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            return DesktopManager.VirtualDesktopPinnedApps.IsAppIdPinned( DesktopManager.GetAppId( hWnd ) );\n        }\n\n        public static void PinApplication( IntPtr hWnd )\n        {\n            // pin application for window to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var appId = DesktopManager.GetAppId( hWnd );\n            if ( !DesktopManager.VirtualDesktopPinnedApps.IsAppIdPinned( appId ) )\n            {\n                // pin only if not already pinned\n                DesktopManager.VirtualDesktopPinnedApps.PinAppID( appId );\n            }\n        }\n\n        public static void UnpinApplication( IntPtr hWnd )\n        {\n            // unpin application for window from all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var view  = hWnd.GetApplicationView();\n            var appId = DesktopManager.GetAppId( hWnd );\n            if ( DesktopManager.VirtualDesktopPinnedApps.IsAppIdPinned( appId ) )\n            {\n                // unpin only if pinned\n                DesktopManager.VirtualDesktopPinnedApps.UnpinAppID( appId );\n            }\n        }\n\n        public static Desktop? FromId( Guid guid )\n        {\n            try\n            {\n                return new Desktop( DesktopManager.VirtualDesktopManagerInternal.FindDesktop( ref guid ) );\n            }\n            catch\n            {\n                return null;\n            }\n        }\n    }\n}"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop11_21H2/VirtualDesktop11_21H2.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFrameworks>net6.0-windows</TargetFrameworks>\n        <Nullable>enable</Nullable>\n        <CsWinRTEnabled>false</CsWinRTEnabled>\n        <LangVersion>9</LangVersion>\n    </PropertyGroup>\n\n    <ItemGroup Condition=\" '$(TargetFramework)' == 'net5.0-windows' Or '$(TargetFramework)' == 'net6.0-windows' \">\n        <PackageReference Include=\"Microsoft.Windows.CsWinRT\" Version=\"1.4.1\" />\n    </ItemGroup>\n\n    <ItemGroup>\n        <ProjectReference Include=\"..\\..\\Bridge\\Bridge.csproj\" />\n    </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop11_21H2/VirtualDesktopManager.cs",
    "content": "﻿// Author: Markus Scholtes, 2021\n// Version 1.9, 2021-10-08\n// Version for Windows 10 21H2 and Windows 11\n// Compile with:\n// C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\csc.exe VirtualDesktop11.cs\n// Based on http://stackoverflow.com/a/32417530, Windows 10 SDK, github project Grabacr07/VirtualDesktop and own research\n\n/////////////////////////////////////////////////\n// Dylan Cheng (https://github.com/newlooper)\n// added Notifications about desktop\n// added conditional compile for C#/WinRT breaking change on .NET 5.0+\n\nusing System;\nusing System.Runtime.InteropServices;\n#if NET5_0_OR_GREATER\nusing WinRT;\n#endif\n\nnamespace VirtualDesktop\n{\n    public static class DesktopManager\n    {\n        private static  DisposableNotification             _disposableNotification;\n        private static  IVirtualDesktopNotificationService VirtualDesktopNotificationService;\n        internal static IVirtualDesktopManagerInternal     VirtualDesktopManagerInternal;\n        internal static IVirtualDesktopManager             VirtualDesktopManager;\n        internal static IVirtualDesktopPinnedApps          VirtualDesktopPinnedApps;\n        public static   IApplicationViewCollection         ApplicationViewCollection;\n\n        static DesktopManager()\n        {\n            if ( Environment.OSVersion.Version is {Major: 10, Build: >= 22000} )\n                Init();\n        }\n\n        public static void ResetDesktopManager()\n        {\n            Init();\n        }\n\n        private static void Init()\n        {\n            var shell = (IServiceProvider10)Activator.CreateInstance( Type.GetTypeFromCLSID( Guids.CLSID_ImmersiveShell ) );\n\n            VirtualDesktopManager = (IVirtualDesktopManager)Activator.CreateInstance(\n                Type.GetTypeFromCLSID( Guids.CLSID_VirtualDesktopManager ) );\n\n            VirtualDesktopManagerInternal = (IVirtualDesktopManagerInternal)shell.QueryService(\n                Guids.CLSID_VirtualDesktopManagerInternal,\n                typeof( IVirtualDesktopManagerInternal ).GUID );\n            ApplicationViewCollection = (IApplicationViewCollection)shell.QueryService(\n                typeof( IApplicationViewCollection ).GUID,\n                typeof( IApplicationViewCollection ).GUID );\n            VirtualDesktopPinnedApps = (IVirtualDesktopPinnedApps)shell.QueryService(\n                Guids.CLSID_VirtualDesktopPinnedApps,\n                typeof( IVirtualDesktopPinnedApps ).GUID );\n            VirtualDesktopNotificationService = (IVirtualDesktopNotificationService)shell.QueryService(\n                Guids.CLSID_VirtualDesktopNotificationService,\n                typeof( IVirtualDesktopNotificationService ).GUID );\n\n            _disposableNotification = new DisposableNotification();\n            _disposableNotification.DwCookie = VirtualDesktopNotificationService.Register( new EventProxy() );\n        }\n\n        public static int GetDesktopCount()\n        {\n            try\n            {\n                return VirtualDesktopManagerInternal.GetCount( IntPtr.Zero );\n            }\n            catch\n            {\n                ResetDesktopManager();\n                return VirtualDesktopManagerInternal.GetCount( IntPtr.Zero );\n            }\n        }\n\n        public static IVirtualDesktop GetDesktop( int index )\n        {\n            // get desktop with index\n            var count = GetDesktopCount();\n            if ( index < 0 || index >= count ) throw new ArgumentOutOfRangeException( nameof( index ) );\n            VirtualDesktopManagerInternal.GetDesktops( IntPtr.Zero, out var desktops );\n            desktops.GetAt( index, typeof( IVirtualDesktop ).GUID, out var objDesktop );\n            Marshal.ReleaseComObject( desktops );\n            return (IVirtualDesktop)objDesktop;\n        }\n\n        internal static int GetDesktopIndex( IVirtualDesktop desktop )\n        {\n            // get index of desktop\n            var count    = GetDesktopCount();\n            var index    = -1;\n            var idSearch = desktop.GetId();\n            VirtualDesktopManagerInternal.GetDesktops( IntPtr.Zero, out var desktops );\n            for ( var i = 0; i < count; i++ )\n            {\n                desktops.GetAt( i, typeof( IVirtualDesktop ).GUID, out var objDesktop );\n                if ( idSearch.CompareTo( ( (IVirtualDesktop)objDesktop ).GetId() ) == 0 )\n                {\n                    index = i;\n                    break;\n                }\n            }\n\n            Marshal.ReleaseComObject( desktops );\n            return index;\n        }\n\n        internal static IApplicationView GetApplicationView( this IntPtr hWnd )\n        {\n            // get application view to window handle\n            ApplicationViewCollection.GetViewForHWnd( hWnd, out var view );\n            return view;\n        }\n\n        internal static string GetAppId( IntPtr hWnd )\n        {\n            // get Application ID to window handle\n            hWnd.GetApplicationView().GetAppUserModelId( out var appId );\n            return appId;\n        }\n\n        public static int GetViewCount()\n        {\n            ApplicationViewCollection.GetViews( out var objectArray );\n            objectArray.GetCount( out var count );\n            Marshal.ReleaseComObject( objectArray );\n            return count;\n        }\n\n        public static event EventHandler<IVirtualDesktop>?                         Created;\n        public static event EventHandler<VirtualDesktopDestroyEventArgs>?          DestroyBegin;\n        public static event EventHandler<VirtualDesktopDestroyEventArgs>?          DestroyFailed;\n        public static event EventHandler<VirtualDesktopDestroyEventArgs>?          Destroyed;\n        public static event EventHandler<VirtualDesktopChangedEventArgs>?          CurrentChanged;\n        public static event EventHandler<VirtualDesktopMovedEventArgs>?            Moved;\n        public static event EventHandler<VirtualDesktopRenamedEventArgs>?          Renamed;\n        public static event EventHandler<VirtualDesktopWallpaperChangedEventArgs>? WallpaperChanged;\n\n        private class DisposableNotification : IDisposable\n        {\n            private bool _isDisposed;\n            public  uint DwCookie { private get; set; }\n\n            public void Dispose()\n            {\n                if ( _isDisposed ) return;\n\n                VirtualDesktopNotificationService.Unregister( DwCookie );\n                _isDisposed = true;\n            }\n        }\n\n        private class EventProxy : IVirtualDesktopNotification\n        {\n            public void ViewVirtualDesktopChanged( IApplicationView pView )\n            {\n                // throw new NotImplementedException();\n            }\n\n            public void CurrentVirtualDesktopChanged( IObjectArray p0, IVirtualDesktop pDesktopOld, IVirtualDesktop pDesktopNew )\n            {\n                CurrentChanged?.Invoke( this, new VirtualDesktopChangedEventArgs( pDesktopOld, pDesktopNew ) );\n            }\n\n            public void VirtualDesktopCreated( IObjectArray p0, IVirtualDesktop pDesktop )\n            {\n                Created?.Invoke( this, pDesktop );\n            }\n\n            public void VirtualDesktopDestroyBegin( IObjectArray p0, IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback )\n            {\n                DestroyBegin?.Invoke( this, new VirtualDesktopDestroyEventArgs( pDesktopDestroyed, pDesktopFallback ) );\n            }\n\n            public void VirtualDesktopDestroyFailed( IObjectArray p0, IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback )\n            {\n                DestroyFailed?.Invoke( this, new VirtualDesktopDestroyEventArgs( pDesktopDestroyed, pDesktopFallback ) );\n            }\n\n            public void VirtualDesktopDestroyed( IObjectArray p0, IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback )\n            {\n                Destroyed?.Invoke( this, new VirtualDesktopDestroyEventArgs( pDesktopDestroyed, pDesktopFallback ) );\n            }\n\n            public void Proc7( int p0 )\n            {\n                // throw new NotImplementedException();\n            }\n\n            public void VirtualDesktopMoved( IObjectArray p0, IVirtualDesktop pDesktop, int nIndexFrom, int nIndexTo )\n            {\n                Moved?.Invoke( this, new VirtualDesktopMovedEventArgs( pDesktop, nIndexFrom, nIndexTo ) );\n            }\n\n#if NET5_0_OR_GREATER\n            public void VirtualDesktopRenamed( IVirtualDesktop pDesktop, IntPtr newName )\n            {\n                var name = MarshalString.FromAbi( newName );\n                Renamed?.Invoke( this, new VirtualDesktopRenamedEventArgs( pDesktop, name ) );\n            }\n#else\n            public void VirtualDesktopRenamed( IVirtualDesktop pDesktop, string chName )\n            {\n                Renamed?.Invoke( this, new VirtualDesktopRenamedEventArgs( pDesktop, chName ) );\n            }\n#endif\n\n#if NET5_0_OR_GREATER\n            public void VirtualDesktopWallpaperChanged( IVirtualDesktop pDesktop, IntPtr newPath )\n            {\n                var path = MarshalString.FromAbi( newPath );\n                WallpaperChanged?.Invoke( this, new VirtualDesktopWallpaperChangedEventArgs( pDesktop, path ) );\n            }\n#else\n            public void VirtualDesktopWallpaperChanged( IVirtualDesktop pDesktop, string chPath )\n            {\n                WallpaperChanged?.Invoke( this, new VirtualDesktopWallpaperChangedEventArgs( pDesktop, chPath ) );\n            }\n#endif\n        }\n    }\n\n    public class VirtualDesktopRenamedEventArgs : EventArgs\n    {\n        public VirtualDesktopRenamedEventArgs( IVirtualDesktop desktop, string name )\n        {\n            Desktop = desktop;\n            Name = name;\n        }\n\n        public IVirtualDesktop Desktop { get; }\n        public string          Name    { get; }\n    }\n\n    public class VirtualDesktopWallpaperChangedEventArgs : EventArgs\n    {\n        public VirtualDesktopWallpaperChangedEventArgs( IVirtualDesktop desktop, string path )\n        {\n            Desktop = desktop;\n            Path = path;\n        }\n\n        public IVirtualDesktop Desktop { get; }\n        public string          Path    { get; }\n    }\n\n\n    public class VirtualDesktopChangedEventArgs : EventArgs\n    {\n        public VirtualDesktopChangedEventArgs( IVirtualDesktop oldDesktop, IVirtualDesktop newDesktop )\n        {\n            OldDesktop = oldDesktop;\n            NewDesktop = newDesktop;\n        }\n\n        public IVirtualDesktop OldDesktop { get; }\n        public IVirtualDesktop NewDesktop { get; }\n    }\n\n    public class VirtualDesktopMovedEventArgs : EventArgs\n    {\n        public VirtualDesktopMovedEventArgs( IVirtualDesktop desktop, int oldIndex, int newIndex )\n        {\n            Desktop = desktop;\n            OldIndex = oldIndex;\n            NewIndex = newIndex;\n        }\n\n        public IVirtualDesktop Desktop  { get; }\n        public int             OldIndex { get; }\n        public int             NewIndex { get; }\n    }\n\n    public class VirtualDesktopDestroyEventArgs : EventArgs\n    {\n        public VirtualDesktopDestroyEventArgs( IVirtualDesktop destroyed, IVirtualDesktop fallback )\n        {\n            Destroyed = destroyed;\n            Fallback = fallback;\n        }\n\n        public IVirtualDesktop Destroyed { get; }\n        public IVirtualDesktop Fallback  { get; }\n    }\n}"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop11_23H2/COM.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Runtime.InteropServices;\n\nnamespace VirtualDesktop\n{\n    internal static class Guids\n    {\n        public static readonly Guid CLSID_ImmersiveShell                    = new( \"C2F03A33-21F5-47FA-B4BB-156362A2F239\" );\n        public static readonly Guid CLSID_VirtualDesktopManagerInternal     = new( \"C5E0CDCA-7B6E-41B2-9FC4-D93975CC467B\" );\n        public static readonly Guid CLSID_VirtualDesktopManager             = new( \"AA509086-5CA9-4C25-8F95-589D3C07B48A\" );\n        public static readonly Guid CLSID_VirtualDesktopPinnedApps          = new( \"B5A399E7-1C87-46B8-88E9-FC5747B171BD\" );\n        public static readonly Guid CLSID_VirtualDesktopNotificationService = new( \"A501FDEC-4A09-464C-AE4E-1B9C21B84918\" );\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct Size\n    {\n        public int X;\n        public int Y;\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct Rect\n    {\n        public int Left;\n        public int Top;\n        public int Right;\n        public int Bottom;\n    }\n\n    public enum APPLICATION_VIEW_CLOAK_TYPE : int\n    {\n        AVCT_NONE            = 0,\n        AVCT_DEFAULT         = 1,\n        AVCT_VIRTUAL_DESKTOP = 2\n    }\n\n    public enum APPLICATION_VIEW_COMPATIBILITY_POLICY : int\n    {\n        AVCP_NONE                = 0,\n        AVCP_SMALL_SCREEN        = 1,\n        AVCP_TABLET_SMALL_SCREEN = 2,\n        AVCP_VERY_SMALL_SCREEN   = 3,\n        AVCP_HIGH_SCALE_FACTOR   = 4\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"372E1D3B-38D3-42E4-A15B-8AB2B178F513\" )]\n    public interface IApplicationView\n    {\n        void GetIIdsSlot();\n        void GetRuntimeClassNameSlot();\n        void GetTrustLevelSlot();\n        int  SetFocus();\n        int  SwitchTo();\n        int  TryInvokeBack( IntPtr /* IAsyncCallback* */ callback );\n        int  GetThumbnailWindow( out IntPtr hWnd );\n        int  GetMonitor( out         IntPtr /* IImmersiveMonitor */ immersiveMonitor );\n        int  GetVisibility( out      int visibility );\n        int  SetCloak( APPLICATION_VIEW_CLOAK_TYPE cloakType, int unknown );\n        int  GetPosition( ref Guid guid /* GUID for IApplicationViewPosition */, out IntPtr /* IApplicationViewPosition** */ position );\n        int  SetPosition( ref IntPtr /* IApplicationViewPosition* */ position );\n        int  InsertAfterWindow( IntPtr hWnd );\n        int  GetExtendedFramePosition( out                              Rect rect );\n        int  GetAppUserModelId( [MarshalAs( UnmanagedType.LPWStr )] out string id );\n        int  SetAppUserModelId( string id );\n        int  IsEqualByAppUserModelId( string id, out int result );\n        int  GetViewState( out uint state );\n        int  SetViewState( uint state );\n        int  GetNeediness( out               int neediness );\n        int  GetLastActivationTimestamp( out ulong timestamp );\n        int  SetLastActivationTimestamp( ulong timestamp );\n        int  GetVirtualDesktopId( out Guid guid );\n        int  SetVirtualDesktopId( ref Guid guid );\n        int  GetShowInSwitchers( out  int flag );\n        int  SetShowInSwitchers( int flag );\n        int  GetScaleFactor( out             int factor );\n        int  CanReceiveInput( out            bool canReceiveInput );\n        int  GetCompatibilityPolicyType( out APPLICATION_VIEW_COMPATIBILITY_POLICY flags );\n        int  SetCompatibilityPolicyType( APPLICATION_VIEW_COMPATIBILITY_POLICY flags );\n        int  GetSizeConstraints( IntPtr /* IImmersiveMonitor* */ monitor, out Size size1, out Size size2 );\n        int  GetSizeConstraintsForDpi( uint uint1, out Size size1, out Size size2 );\n        int  SetSizeConstraintsForDpi( ref uint uint1, ref Size size1, ref Size size2 );\n        int  OnMinSizePreferencesUpdated( IntPtr hWnd );\n        int  ApplyOperation( IntPtr /* IApplicationViewOperation* */ operation );\n        int  IsTray( out                  bool isTray );\n        int  IsInHighZOrderBand( out      bool isInHighZOrderBand );\n        int  IsSplashScreenPresented( out bool isSplashScreenPresented );\n        int  Flash();\n        int  GetRootSwitchableOwner( out                              IApplicationView rootSwitchableOwner );\n        int  EnumerateOwnershipTree( out                              IObjectArray     ownershipTree );\n        int  GetEnterpriseId( [MarshalAs( UnmanagedType.LPWStr )] out string           enterpriseId );\n        int  IsMirrored( out                                          bool             isMirrored );\n        int  Unknown1( out                                            int              unknown );\n        int  Unknown2( out                                            int              unknown );\n        int  Unknown3( out                                            int              unknown );\n        int  Unknown4( out                                            int              unknown );\n        int  Unknown5( out                                            int              unknown );\n        int  Unknown6( int                                                             unknown );\n        int  Unknown7();\n        int  Unknown8( out int   unknown );\n        int  Unknown9( int       unknown );\n        int  Unknown10( int      unknownX, int unknownY );\n        int  Unknown11( int      unknown );\n        int  Unknown12( out Size size1 );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"1841C6D7-4F9D-42C0-AF41-8747538F10E5\" )]\n    public interface IApplicationViewCollection\n    {\n        int  GetViews( out         IObjectArray array );\n        int  GetViewsByZOrder( out IObjectArray array );\n        int  GetViewsByAppUserModelId( string   id,          out IObjectArray     array );\n        int  GetViewForHWnd( IntPtr             hWnd,        out IApplicationView view );\n        int  GetViewForApplication( object      application, out IApplicationView view );\n        int  GetViewForAppUserModelId( string   id,          out IApplicationView view );\n        int  GetViewInFocus( out IntPtr         view );\n        int  Unknown1( out       IntPtr         view );\n        void RefreshCollection();\n        int  RegisterForApplicationViewChanges( object listener, out int cookie );\n        int  UnregisterForApplicationViewChanges( int  cookie );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"3F07F4BE-B107-441A-AF0F-39D82529072C\" )]\n    public interface IVirtualDesktop\n    {\n        bool IsViewVisible( IApplicationView view );\n        Guid GetId();\n\n#if NET5_0_OR_GREATER\n        public void GetString( out IntPtr hstr );\n#else\n        [return: MarshalAs( UnmanagedType.HString )]\n        string GetName();\n#endif\n\n        [return: MarshalAs( UnmanagedType.HString )]\n        string GetWallpaperPath();\n\n        bool IsRemote();\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"A3175F2D-239C-4BD2-8AA0-EEBA8B0B138E\" )]\n    internal interface IVirtualDesktopManagerInternal\n    {\n        int             GetCount();\n        void            MoveViewToDesktop( IApplicationView   view, IVirtualDesktop desktop );\n        bool            CanViewMoveDesktops( IApplicationView view );\n        IVirtualDesktop GetCurrentDesktop();\n        void            GetDesktops( out IObjectArray desktops );\n\n        [PreserveSig]\n        int GetAdjacentDesktop( IVirtualDesktop from, int direction, out IVirtualDesktop desktop );\n\n        void            SwitchDesktop( IVirtualDesktop desktop );\n        IVirtualDesktop CreateDesktop();\n        void            MoveDesktop( IVirtualDesktop                         desktop, int             nIndex );\n        void            RemoveDesktop( IVirtualDesktop                       desktop, IVirtualDesktop fallback );\n        IVirtualDesktop FindDesktop( ref Guid                                desktopId );\n        void            GetDesktopSwitchIncludeExcludeViews( IVirtualDesktop desktop, out IObjectArray unknown1, out IObjectArray unknown2 );\n#if NET5_0_OR_GREATER\n        void SetName( IVirtualDesktop      desktop, IntPtr newName );\n        void SetWallpaper( IVirtualDesktop desktop, IntPtr path );\n#else\n        void SetDesktopName( IVirtualDesktop      desktop, [MarshalAs( UnmanagedType.HString )] string name );\n        void SetDesktopWallpaper( IVirtualDesktop desktop, [MarshalAs( UnmanagedType.HString )] string path );\n#endif\n        void UpdateWallpaperPathForAllDesktops( [MarshalAs( UnmanagedType.HString )] string path );\n        void CopyDesktopState( IApplicationView                                             pView0, IApplicationView    pView1 );\n        void CreateRemoteDesktop( [MarshalAs( UnmanagedType.HString )] string               path,   out IVirtualDesktop desktop );\n        void SwitchRemoteDesktop( IVirtualDesktop                                           desktop );\n        void SwitchDesktopWithAnimation( IVirtualDesktop                                    desktop );\n        void GetLastActiveDesktop( out IVirtualDesktop                                      desktop );\n        void WaitForAnimationToComplete();\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"A5CD92FF-29BE-454C-8D04-D82879FB3F1B\" )]\n    internal interface IVirtualDesktopManager\n    {\n        bool IsWindowOnCurrentVirtualDesktop( IntPtr topLevelWindow );\n        Guid GetWindowDesktopId( IntPtr              topLevelWindow );\n        void MoveWindowToDesktop( IntPtr             topLevelWindow, ref Guid desktopId );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"4CE81583-1E4C-4632-A621-07A53543148F\" )]\n    internal interface IVirtualDesktopPinnedApps\n    {\n        bool IsAppIdPinned( string          appId );\n        void PinAppID( string               appId );\n        void UnpinAppID( string             appId );\n        bool IsViewPinned( IApplicationView applicationView );\n        void PinView( IApplicationView      applicationView );\n        void UnpinView( IApplicationView    applicationView );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"92CA9DCD-5622-4BBA-A805-5E9F541BD8C9\" )]\n    public interface IObjectArray\n    {\n        void GetCount( out int count );\n        void GetAt( int        index, ref Guid iid, [MarshalAs( UnmanagedType.Interface )] out object obj );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"6D5140C1-7436-11CE-8034-00AA006009FA\" )]\n    internal interface IServiceProvider10\n    {\n        [return: MarshalAs( UnmanagedType.IUnknown )]\n        object QueryService( ref Guid service, ref Guid riid );\n    }\n\n    [ComImport]\n    [Guid( \"B287FA1C-7771-471A-A2DF-9B6B21F0D675\" )]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    public interface IVirtualDesktopNotification\n    {\n        void VirtualDesktopCreated( IVirtualDesktop       pDesktop );\n        void VirtualDesktopDestroyBegin( IVirtualDesktop  pDesktopDestroyed, IVirtualDesktop pDesktopFallback );\n        void VirtualDesktopDestroyFailed( IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback );\n        void VirtualDesktopDestroyed( IVirtualDesktop     pDesktopDestroyed, IVirtualDesktop pDesktopFallback );\n        void VirtualDesktopMoved( IVirtualDesktop         pDesktop,          int             nIndexFrom, int nIndexTo );\n#if NET5_0_OR_GREATER\n        void VirtualDesktopRenamed( IVirtualDesktop pDesktop, IntPtr newName );\n#else\n        void VirtualDesktopRenamed( IVirtualDesktop pDesktop, [MarshalAs( UnmanagedType.HString )] string chName );\n#endif\n        void ViewVirtualDesktopChanged( IApplicationView   pView );\n        void CurrentVirtualDesktopChanged( IVirtualDesktop pDesktopOld, IVirtualDesktop pDesktopNew );\n\n#if NET5_0_OR_GREATER\n        void VirtualDesktopWallpaperChanged( IVirtualDesktop pDesktop, IntPtr newPath );\n#else\n        void VirtualDesktopWallpaperChanged( IVirtualDesktop pDesktop, [MarshalAs( UnmanagedType.HString )] string chPath );\n#endif\n        void VirtualDesktopSwitched( IVirtualDesktop        pDesktop );\n        void RemoteVirtualDesktopConnected( IVirtualDesktop pDesktop );\n    }\n\n    [ComImport]\n    [Guid( \"0cd45e71-d927-4f15-8b0a-8fef525337bf\" )]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    public interface IVirtualDesktopNotificationService\n    {\n        uint Register( IVirtualDesktopNotification pNotification );\n        void Unregister( uint                      dwCookie );\n    }\n}"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop11_23H2/VirtualDesktop.cs",
    "content": "// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Diagnostics;\nusing System.Runtime.InteropServices;\nusing VirtualSpace;\n#if NET5_0_OR_GREATER\nusing WinRT;\n#endif\n\nnamespace VirtualDesktop\n{\n    public class Desktop : IDesktop\n    {\n        private readonly IVirtualDesktop _ivd;\n\n        private Desktop( IVirtualDesktop desktop )\n        {\n            _ivd = desktop;\n        }\n\n        public Guid Guid => _ivd.GetId();\n\n        public static int Count =>\n            // return the number of desktops\n            DesktopManager.GetDesktopCount();\n\n        public static Desktop Current\n        {\n            get\n            {\n                // returns current desktop\n                try\n                {\n                    return new Desktop( DesktopManager.VirtualDesktopManagerInternal.GetCurrentDesktop() );\n                }\n                catch\n                {\n                    DesktopManager.ResetDesktopManager();\n                    return new Desktop( DesktopManager.VirtualDesktopManagerInternal.GetCurrentDesktop() );\n                }\n            }\n        }\n\n        public bool IsVisible =>\n            // return true if this desktop is the current displayed one\n            ReferenceEquals( _ivd, DesktopManager.VirtualDesktopManagerInternal.GetCurrentDesktop() );\n\n        public Desktop Left\n        {\n            // return desktop at the left of this one, null if none\n            get\n            {\n                var hr = DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 3, out var desktop ); // 3 = LeftDirection\n                if ( hr == 0 )\n                    return new Desktop( desktop );\n                else\n                    return null;\n            }\n        }\n\n        public Desktop Right\n        {\n            // return desktop at the right of this one, null if none\n            get\n            {\n                var hr = DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 4, out var desktop ); // 4 = RightDirection\n                if ( hr == 0 )\n                    return new Desktop( desktop );\n                else\n                    return null;\n            }\n        }\n\n        // get process id to window handle\n        [DllImport( \"user32.dll\" )]\n        private static extern int GetWindowThreadProcessId( IntPtr hWnd, out int lpdwProcessId );\n\n        // get handle of active window\n        [DllImport( \"user32.dll\" )]\n        private static extern IntPtr GetForegroundWindow();\n\n        public override int GetHashCode()\n        {\n            // get hash\n            return _ivd.GetHashCode();\n        }\n\n        public override bool Equals( object? obj )\n        {\n            // compare with object\n            return obj is Desktop desk && ReferenceEquals( _ivd, desk._ivd );\n        }\n\n        public static Desktop FromIndex( int index )\n        {\n            // return desktop object from index (-> index = 0..Count-1)\n            return new Desktop( DesktopManager.GetDesktop( index ) );\n        }\n\n        public static Desktop FromWindow( IntPtr hWnd )\n        {\n            // return desktop object to desktop on which window <hWnd> is displayed\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var id = DesktopManager.VirtualDesktopManager.GetWindowDesktopId( hWnd );\n            return new Desktop( DesktopManager.VirtualDesktopManagerInternal.FindDesktop( ref id ) );\n        }\n\n        public static int SysIndexFromDesktop( Desktop desktop )\n        {\n            // return index of desktop object or -1 if not found\n            if ( desktop == null ) return -1;\n            return DesktopManager.GetDesktopIndex( desktop._ivd );\n        }\n\n        public static string DesktopNameFromDesktop( Desktop desktop )\n        {\n            // return name of desktop or \"Desktop n\" if it has no name\n\n            // get desktop name\n            string desktopName = null;\n            try\n            {\n#if NET5_0_OR_GREATER\n                desktop._ivd.GetString( out var hstr );\n                desktopName = MarshalString.FromAbi( hstr );\n#else\n                desktopName = desktop._ivd.GetName();\n#endif\n            }\n            catch ( Exception )\n            {\n            }\n\n            // no name found, generate generic name\n            if ( string.IsNullOrEmpty( desktopName ) )\n            {\n                // create name \"Desktop n\" (n = number starting with 1)\n                desktopName = \"Desktop \" + ( DesktopManager.GetDesktopIndex( desktop._ivd ) + 1 ).ToString();\n            }\n\n            return desktopName;\n        }\n\n        public static string DesktopNameFromIndex( int index )\n        {\n            // return name of desktop from index (-> index = 0..Count-1) or \"Desktop n\" if it has no name\n\n            // get desktop name\n            string desktopName = null;\n            try\n            {\n#if NET5_0_OR_GREATER\n                DesktopManager.GetDesktop( index ).GetString( out var hstr );\n                desktopName = MarshalString.FromAbi( hstr );\n#else\n                desktopName = DesktopManager.GetDesktop( index ).GetName();\n#endif\n            }\n            catch\n            {\n            }\n\n            // no name found, generate generic name\n            if ( string.IsNullOrEmpty( desktopName ) )\n            {\n                // create name \"Desktop n\" (n = number starting with 1)\n                desktopName = \"Desktop \" + ( index + 1 ).ToString();\n            }\n\n            return desktopName;\n        }\n\n        public static bool HasDesktopNameFromIndex( int index )\n        {\n            // return true is desktop is named or false if it has no name\n\n            // read desktop name in registry\n            string desktopName = null;\n            try\n            {\n#if NET5_0_OR_GREATER\n                DesktopManager.GetDesktop( index ).GetString( out var hstr );\n                desktopName = MarshalString.FromAbi( hstr );\n#else\n                desktopName = DesktopManager.GetDesktop( index ).GetName();\n#endif\n            }\n            catch\n            {\n            }\n\n            // name found?\n            if ( string.IsNullOrEmpty( desktopName ) )\n                return false;\n            else\n                return true;\n        }\n\n        public static string DesktopWallpaperFromIndex( int index )\n        {\n            // return name of desktop wallpaper from index (-> index = 0..Count-1)\n\n            // get desktop name\n            var desktopWpPath = \"\";\n            try\n            {\n                desktopWpPath = DesktopManager.GetDesktop( index ).GetWallpaperPath();\n            }\n            catch\n            {\n            }\n\n            return desktopWpPath;\n        }\n\n        public static int SearchDesktop( string partialName )\n        {\n            // get index of desktop with partial name, return -1 if no desktop found\n            var index = -1;\n\n            for ( var i = 0; i < DesktopManager.GetDesktopCount(); i++ )\n            {\n                // loop through all virtual desktops and compare partial name to desktop name\n                if ( DesktopNameFromIndex( i ).ToUpper().IndexOf( partialName.ToUpper() ) >= 0 )\n                {\n                    index = i;\n                    break;\n                }\n            }\n\n            return index;\n        }\n\n        public static Desktop Create()\n        {\n            // create a new desktop\n            return new Desktop( DesktopManager.VirtualDesktopManagerInternal.CreateDesktop() );\n        }\n\n        public void Remove( Desktop? fallback = null )\n        {\n            // destroy desktop and switch to <fallback>\n            IVirtualDesktop fallbackDesktop;\n            if ( fallback == null )\n            {\n                // if no fallback is given use desktop to the left except for desktop 0.\n                var dtToCheck = new Desktop( DesktopManager.GetDesktop( 0 ) );\n                if ( Equals( dtToCheck ) )\n                {\n                    // desktop 0: set fallback to second desktop (= \"right\" desktop)\n                    DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 4, out fallbackDesktop ); // 4 = RightDirection\n                }\n                else\n                {\n                    // set fallback to \"left\" desktop\n                    DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 3, out fallbackDesktop ); // 3 = LeftDirection\n                }\n            }\n            else\n                // set fallback desktop\n                fallbackDesktop = fallback._ivd;\n\n            DesktopManager.VirtualDesktopManagerInternal.RemoveDesktop( _ivd, fallbackDesktop );\n        }\n\n        public static void RemoveAll()\n        {\n            // remove all desktops but visible\n            // DesktopManager.VirtualDesktopManagerInternal.SetDesktopIsPerMonitor( true );\n        }\n\n        public void Move( int index )\n        {\n            // move current desktop to desktop in index (-> index = 0..Count-1)\n            DesktopManager.VirtualDesktopManagerInternal.MoveDesktop( _ivd, index );\n        }\n\n        public void SetName( string name )\n        {\n            // set name for desktop, empty string removes name\n#if NET5_0_OR_GREATER\n            var newName = MarshalString.CreateMarshaler( name );\n            DesktopManager.VirtualDesktopManagerInternal.SetName( _ivd, MarshalString.GetAbi( newName ) );\n#else\n            DesktopManager.VirtualDesktopManagerInternal.SetDesktopName( _ivd, name );\n#endif\n        }\n\n        public void SetWallpaperPath( string path )\n        {\n            // set path for wallpaper, empty string removes path\n            if ( string.IsNullOrEmpty( path ) ) throw new ArgumentNullException();\n\n#if NET5_0_OR_GREATER\n            var newPath = MarshalString.CreateMarshaler( path );\n            DesktopManager.VirtualDesktopManagerInternal.SetWallpaper( _ivd, MarshalString.GetAbi( newPath ) );\n#else\n            DesktopManager.VirtualDesktopManagerInternal.SetDesktopWallpaper( _ivd, path );\n#endif\n        }\n\n        public static void SetAllWallpaperPaths( string path )\n        {\n            // set wallpaper path for all desktops\n            if ( string.IsNullOrEmpty( path ) ) throw new ArgumentNullException();\n            DesktopManager.VirtualDesktopManagerInternal.UpdateWallpaperPathForAllDesktops( path );\n        }\n\n        public void MakeVisible()\n        {\n            // make this desktop visible\n            DesktopManager.VirtualDesktopManagerInternal.SwitchDesktop( _ivd );\n        }\n\n        public void MoveWindow( IntPtr hWnd )\n        {\n            // move window to this desktop\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            _ = GetWindowThreadProcessId( hWnd, out var processId );\n\n            if ( Process.GetCurrentProcess().Id == processId )\n            {\n                // window of process\n                try // the easy way (if we are owner)\n                {\n                    DesktopManager.VirtualDesktopManager.MoveWindowToDesktop( hWnd, _ivd.GetId() );\n                }\n                catch // window of process, but we are not the owner\n                {\n                    DesktopManager.ApplicationViewCollection.GetViewForHWnd( hWnd, out var view );\n                    DesktopManager.VirtualDesktopManagerInternal.MoveViewToDesktop( view, _ivd );\n                }\n            }\n            else\n            {\n                // window of other process\n                DesktopManager.ApplicationViewCollection.GetViewForHWnd( hWnd, out var view );\n                try\n                {\n                    DesktopManager.VirtualDesktopManagerInternal.MoveViewToDesktop( view, _ivd );\n                }\n                catch\n                {\n                    // could not move active window, try main window (or whatever windows thinks is the main window)\n                    DesktopManager.ApplicationViewCollection.GetViewForHWnd(\n                        Process.GetProcessById( processId ).MainWindowHandle,\n                        out view );\n                    DesktopManager.VirtualDesktopManagerInternal.MoveViewToDesktop( view, _ivd );\n                }\n            }\n        }\n\n        public void MoveActiveWindow()\n        {\n            // move active window to this desktop\n            MoveWindow( GetForegroundWindow() );\n        }\n\n        public bool HasWindow( IntPtr hWnd )\n        {\n            // return true if window is on this desktop\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            return _ivd.GetId() == DesktopManager.VirtualDesktopManager.GetWindowDesktopId( hWnd );\n        }\n\n        public static bool IsWindowPinned( IntPtr hWnd )\n        {\n            // return true if window is pinned to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            return DesktopManager.VirtualDesktopPinnedApps.IsViewPinned( hWnd.GetApplicationView() );\n        }\n\n        public static void PinWindow( IntPtr hWnd )\n        {\n            // pin window to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var view = hWnd.GetApplicationView();\n            if ( !DesktopManager.VirtualDesktopPinnedApps.IsViewPinned( view ) )\n            {\n                // pin only if not already pinned\n                DesktopManager.VirtualDesktopPinnedApps.PinView( view );\n            }\n        }\n\n        public static void UnpinWindow( IntPtr hWnd )\n        {\n            // unpin window from all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var view = hWnd.GetApplicationView();\n            if ( DesktopManager.VirtualDesktopPinnedApps.IsViewPinned( view ) )\n            {\n                // unpin only if not already unpinned\n                DesktopManager.VirtualDesktopPinnedApps.UnpinView( view );\n            }\n        }\n\n        public static bool IsApplicationPinned( IntPtr hWnd )\n        {\n            // return true if application for window is pinned to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            return DesktopManager.VirtualDesktopPinnedApps.IsAppIdPinned( DesktopManager.GetAppId( hWnd ) );\n        }\n\n        public static void PinApplication( IntPtr hWnd )\n        {\n            // pin application for window to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var appId = DesktopManager.GetAppId( hWnd );\n            if ( !DesktopManager.VirtualDesktopPinnedApps.IsAppIdPinned( appId ) )\n            {\n                // pin only if not already pinned\n                DesktopManager.VirtualDesktopPinnedApps.PinAppID( appId );\n            }\n        }\n\n        public static void UnpinApplication( IntPtr hWnd )\n        {\n            // unpin application for window from all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var view  = hWnd.GetApplicationView();\n            var appId = DesktopManager.GetAppId( hWnd );\n            if ( DesktopManager.VirtualDesktopPinnedApps.IsAppIdPinned( appId ) )\n            {\n                // unpin only if pinned\n                DesktopManager.VirtualDesktopPinnedApps.UnpinAppID( appId );\n            }\n        }\n\n        public static Desktop? FromId( Guid guid )\n        {\n            try\n            {\n                return new Desktop( DesktopManager.VirtualDesktopManagerInternal.FindDesktop( ref guid ) );\n            }\n            catch\n            {\n                return null;\n            }\n        }\n    }\n}"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop11_23H2/VirtualDesktop11_23H2.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFrameworks>net6.0-windows</TargetFrameworks>\n        <Nullable>enable</Nullable>\n        <CsWinRTEnabled>false</CsWinRTEnabled>\n        <LangVersion>9</LangVersion>\n    </PropertyGroup>\n\n    <ItemGroup Condition=\" '$(TargetFramework)' == 'net5.0-windows' Or '$(TargetFramework)' == 'net6.0-windows' \">\n        <PackageReference Include=\"Microsoft.Windows.CsWinRT\" Version=\"1.4.1\"/>\n    </ItemGroup>\n\n    <ItemGroup>\n        <ProjectReference Include=\"..\\..\\Bridge\\Bridge.csproj\"/>\n    </ItemGroup>\n\n</Project>"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop11_23H2/VirtualDesktopManager.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Runtime.InteropServices;\n#if NET5_0_OR_GREATER\nusing WinRT;\n#endif\n\nnamespace VirtualDesktop\n{\n    public static class DesktopManager\n    {\n        private static  DisposableNotification             _disposableNotification;\n        private static  IVirtualDesktopNotificationService VirtualDesktopNotificationService;\n        internal static IVirtualDesktopManagerInternal     VirtualDesktopManagerInternal;\n        internal static IVirtualDesktopManager             VirtualDesktopManager;\n        internal static IVirtualDesktopPinnedApps          VirtualDesktopPinnedApps;\n        public static   IApplicationViewCollection         ApplicationViewCollection;\n\n        static DesktopManager()\n        {\n            if ( Environment.OSVersion.Version is {Major: 10, Build: >= 22000} )\n                Init();\n        }\n\n        public static void ResetDesktopManager()\n        {\n            Init();\n        }\n\n        private static void Init()\n        {\n            var shell = (IServiceProvider10)Activator.CreateInstance( Type.GetTypeFromCLSID( Guids.CLSID_ImmersiveShell ) );\n\n            VirtualDesktopManager = (IVirtualDesktopManager)Activator.CreateInstance(\n                Type.GetTypeFromCLSID( Guids.CLSID_VirtualDesktopManager ) );\n\n            VirtualDesktopManagerInternal = (IVirtualDesktopManagerInternal)shell.QueryService(\n                Guids.CLSID_VirtualDesktopManagerInternal,\n                typeof( IVirtualDesktopManagerInternal ).GUID );\n            ApplicationViewCollection = (IApplicationViewCollection)shell.QueryService(\n                typeof( IApplicationViewCollection ).GUID,\n                typeof( IApplicationViewCollection ).GUID );\n            VirtualDesktopPinnedApps = (IVirtualDesktopPinnedApps)shell.QueryService(\n                Guids.CLSID_VirtualDesktopPinnedApps,\n                typeof( IVirtualDesktopPinnedApps ).GUID );\n            VirtualDesktopNotificationService = (IVirtualDesktopNotificationService)shell.QueryService(\n                Guids.CLSID_VirtualDesktopNotificationService,\n                typeof( IVirtualDesktopNotificationService ).GUID );\n\n            _disposableNotification = new DisposableNotification();\n            _disposableNotification.DwCookie = VirtualDesktopNotificationService.Register( new EventProxy() );\n        }\n\n        public static int GetDesktopCount()\n        {\n            try\n            {\n                return VirtualDesktopManagerInternal.GetCount();\n            }\n            catch\n            {\n                ResetDesktopManager();\n                return VirtualDesktopManagerInternal.GetCount();\n            }\n        }\n\n        public static IVirtualDesktop GetDesktop( int index )\n        {\n            // get desktop with index\n            var count = GetDesktopCount();\n            if ( index < 0 || index >= count ) throw new ArgumentOutOfRangeException( nameof( index ) );\n            VirtualDesktopManagerInternal.GetDesktops( out var desktops );\n            desktops.GetAt( index, typeof( IVirtualDesktop ).GUID, out var objDesktop );\n            Marshal.ReleaseComObject( desktops );\n            return (IVirtualDesktop)objDesktop;\n        }\n\n        internal static int GetDesktopIndex( IVirtualDesktop desktop )\n        {\n            // get index of desktop\n            var count    = GetDesktopCount();\n            var index    = -1;\n            var idSearch = desktop.GetId();\n            VirtualDesktopManagerInternal.GetDesktops( out var desktops );\n            for ( var i = 0; i < count; i++ )\n            {\n                desktops.GetAt( i, typeof( IVirtualDesktop ).GUID, out var objDesktop );\n                if ( idSearch.CompareTo( ( (IVirtualDesktop)objDesktop ).GetId() ) == 0 )\n                {\n                    index = i;\n                    break;\n                }\n            }\n\n            Marshal.ReleaseComObject( desktops );\n            return index;\n        }\n\n        internal static IApplicationView GetApplicationView( this IntPtr hWnd )\n        {\n            // get application view to window handle\n            ApplicationViewCollection.GetViewForHWnd( hWnd, out var view );\n            return view;\n        }\n\n        internal static string GetAppId( IntPtr hWnd )\n        {\n            // get Application ID to window handle\n            hWnd.GetApplicationView().GetAppUserModelId( out var appId );\n            return appId;\n        }\n\n        public static int GetViewCount()\n        {\n            ApplicationViewCollection.GetViews( out var objectArray );\n            objectArray.GetCount( out var count );\n            Marshal.ReleaseComObject( objectArray );\n            return count;\n        }\n\n        public static event EventHandler<IVirtualDesktop>?                         Created;\n        public static event EventHandler<VirtualDesktopDestroyEventArgs>?          DestroyBegin;\n        public static event EventHandler<VirtualDesktopDestroyEventArgs>?          DestroyFailed;\n        public static event EventHandler<VirtualDesktopDestroyEventArgs>?          Destroyed;\n        public static event EventHandler<VirtualDesktopChangedEventArgs>?          CurrentChanged;\n        public static event EventHandler<VirtualDesktopMovedEventArgs>?            Moved;\n        public static event EventHandler<VirtualDesktopRenamedEventArgs>?          Renamed;\n        public static event EventHandler<VirtualDesktopWallpaperChangedEventArgs>? WallpaperChanged;\n\n        private class DisposableNotification : IDisposable\n        {\n            private bool _isDisposed;\n            public  uint DwCookie { private get; set; }\n\n            public void Dispose()\n            {\n                if ( _isDisposed ) return;\n\n                VirtualDesktopNotificationService.Unregister( DwCookie );\n                _isDisposed = true;\n            }\n        }\n\n        private class EventProxy : IVirtualDesktopNotification\n        {\n            public void ViewVirtualDesktopChanged( IApplicationView pView )\n            {\n                // throw new NotImplementedException();\n            }\n\n            public void CurrentVirtualDesktopChanged( IVirtualDesktop pDesktopOld, IVirtualDesktop pDesktopNew )\n            {\n                CurrentChanged?.Invoke( this, new VirtualDesktopChangedEventArgs( pDesktopOld, pDesktopNew ) );\n            }\n\n            public void VirtualDesktopCreated( IVirtualDesktop pDesktop )\n            {\n                Created?.Invoke( this, pDesktop );\n            }\n\n            public void VirtualDesktopDestroyBegin( IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback )\n            {\n                DestroyBegin?.Invoke( this, new VirtualDesktopDestroyEventArgs( pDesktopDestroyed, pDesktopFallback ) );\n            }\n\n            public void VirtualDesktopDestroyFailed( IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback )\n            {\n                DestroyFailed?.Invoke( this, new VirtualDesktopDestroyEventArgs( pDesktopDestroyed, pDesktopFallback ) );\n            }\n\n            public void VirtualDesktopDestroyed( IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback )\n            {\n                Destroyed?.Invoke( this, new VirtualDesktopDestroyEventArgs( pDesktopDestroyed, pDesktopFallback ) );\n            }\n\n\n            public void VirtualDesktopMoved( IVirtualDesktop pDesktop, int nIndexFrom, int nIndexTo )\n            {\n                Moved?.Invoke( this, new VirtualDesktopMovedEventArgs( pDesktop, nIndexFrom, nIndexTo ) );\n            }\n\n#if NET5_0_OR_GREATER\n            public void VirtualDesktopRenamed( IVirtualDesktop pDesktop, IntPtr newName )\n            {\n                var name = MarshalString.FromAbi( newName );\n                Renamed?.Invoke( this, new VirtualDesktopRenamedEventArgs( pDesktop, name ) );\n            }\n#else\n            public void VirtualDesktopRenamed( IVirtualDesktop pDesktop, string chName )\n            {\n                Renamed?.Invoke( this, new VirtualDesktopRenamedEventArgs( pDesktop, chName ) );\n            }\n#endif\n\n#if NET5_0_OR_GREATER\n            public void VirtualDesktopWallpaperChanged( IVirtualDesktop pDesktop, IntPtr newPath )\n            {\n                var path = MarshalString.FromAbi( newPath );\n                WallpaperChanged?.Invoke( this, new VirtualDesktopWallpaperChangedEventArgs( pDesktop, path ) );\n            }\n#else\n            public void VirtualDesktopWallpaperChanged( IVirtualDesktop pDesktop, string chPath )\n            {\n                WallpaperChanged?.Invoke( this, new VirtualDesktopWallpaperChangedEventArgs( pDesktop, chPath ) );\n            }\n#endif\n            public void VirtualDesktopSwitched( IVirtualDesktop pDesktop )\n            {\n                // throw new NotImplementedException();\n            }\n\n            public void RemoteVirtualDesktopConnected( IVirtualDesktop pDesktop )\n            {\n                // throw new NotImplementedException();\n            }\n        }\n    }\n\n    public class VirtualDesktopRenamedEventArgs : EventArgs\n    {\n        public VirtualDesktopRenamedEventArgs( IVirtualDesktop desktop, string name )\n        {\n            Desktop = desktop;\n            Name = name;\n        }\n\n        public IVirtualDesktop Desktop { get; }\n        public string          Name    { get; }\n    }\n\n    public class VirtualDesktopWallpaperChangedEventArgs : EventArgs\n    {\n        public VirtualDesktopWallpaperChangedEventArgs( IVirtualDesktop desktop, string path )\n        {\n            Desktop = desktop;\n            Path = path;\n        }\n\n        public IVirtualDesktop Desktop { get; }\n        public string          Path    { get; }\n    }\n\n\n    public class VirtualDesktopChangedEventArgs : EventArgs\n    {\n        public VirtualDesktopChangedEventArgs( IVirtualDesktop oldDesktop, IVirtualDesktop newDesktop )\n        {\n            OldDesktop = oldDesktop;\n            NewDesktop = newDesktop;\n        }\n\n        public IVirtualDesktop OldDesktop { get; }\n        public IVirtualDesktop NewDesktop { get; }\n    }\n\n    public class VirtualDesktopMovedEventArgs : EventArgs\n    {\n        public VirtualDesktopMovedEventArgs( IVirtualDesktop desktop, int oldIndex, int newIndex )\n        {\n            Desktop = desktop;\n            OldIndex = oldIndex;\n            NewIndex = newIndex;\n        }\n\n        public IVirtualDesktop Desktop  { get; }\n        public int             OldIndex { get; }\n        public int             NewIndex { get; }\n    }\n\n    public class VirtualDesktopDestroyEventArgs : EventArgs\n    {\n        public VirtualDesktopDestroyEventArgs( IVirtualDesktop destroyed, IVirtualDesktop fallback )\n        {\n            Destroyed = destroyed;\n            Fallback = fallback;\n        }\n\n        public IVirtualDesktop Destroyed { get; }\n        public IVirtualDesktop Fallback  { get; }\n    }\n}"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop11_23H2_3085/COM.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Runtime.InteropServices;\n\nnamespace VirtualDesktop\n{\n    internal static class Guids\n    {\n        public static readonly Guid CLSID_ImmersiveShell                    = new( \"C2F03A33-21F5-47FA-B4BB-156362A2F239\" );\n        public static readonly Guid CLSID_VirtualDesktopManagerInternal     = new( \"C5E0CDCA-7B6E-41B2-9FC4-D93975CC467B\" );\n        public static readonly Guid CLSID_VirtualDesktopManager             = new( \"AA509086-5CA9-4C25-8F95-589D3C07B48A\" );\n        public static readonly Guid CLSID_VirtualDesktopPinnedApps          = new( \"B5A399E7-1C87-46B8-88E9-FC5747B171BD\" );\n        public static readonly Guid CLSID_VirtualDesktopNotificationService = new( \"A501FDEC-4A09-464C-AE4E-1B9C21B84918\" );\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct Size\n    {\n        public int X;\n        public int Y;\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct Rect\n    {\n        public int Left;\n        public int Top;\n        public int Right;\n        public int Bottom;\n    }\n\n    public enum APPLICATION_VIEW_CLOAK_TYPE : int\n    {\n        AVCT_NONE            = 0,\n        AVCT_DEFAULT         = 1,\n        AVCT_VIRTUAL_DESKTOP = 2\n    }\n\n    public enum APPLICATION_VIEW_COMPATIBILITY_POLICY : int\n    {\n        AVCP_NONE                = 0,\n        AVCP_SMALL_SCREEN        = 1,\n        AVCP_TABLET_SMALL_SCREEN = 2,\n        AVCP_VERY_SMALL_SCREEN   = 3,\n        AVCP_HIGH_SCALE_FACTOR   = 4\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"372E1D3B-38D3-42E4-A15B-8AB2B178F513\" )]\n    public interface IApplicationView\n    {\n        void GetIIdsSlot();\n        void GetRuntimeClassNameSlot();\n        void GetTrustLevelSlot();\n        int  SetFocus();\n        int  SwitchTo();\n        int  TryInvokeBack( IntPtr /* IAsyncCallback* */ callback );\n        int  GetThumbnailWindow( out IntPtr hWnd );\n        int  GetMonitor( out         IntPtr /* IImmersiveMonitor */ immersiveMonitor );\n        int  GetVisibility( out      int visibility );\n        int  SetCloak( APPLICATION_VIEW_CLOAK_TYPE cloakType, int unknown );\n        int  GetPosition( ref Guid guid /* GUID for IApplicationViewPosition */, out IntPtr /* IApplicationViewPosition** */ position );\n        int  SetPosition( ref IntPtr /* IApplicationViewPosition* */ position );\n        int  InsertAfterWindow( IntPtr hWnd );\n        int  GetExtendedFramePosition( out                              Rect rect );\n        int  GetAppUserModelId( [MarshalAs( UnmanagedType.LPWStr )] out string id );\n        int  SetAppUserModelId( string id );\n        int  IsEqualByAppUserModelId( string id, out int result );\n        int  GetViewState( out uint state );\n        int  SetViewState( uint state );\n        int  GetNeediness( out               int neediness );\n        int  GetLastActivationTimestamp( out ulong timestamp );\n        int  SetLastActivationTimestamp( ulong timestamp );\n        int  GetVirtualDesktopId( out Guid guid );\n        int  SetVirtualDesktopId( ref Guid guid );\n        int  GetShowInSwitchers( out  int flag );\n        int  SetShowInSwitchers( int flag );\n        int  GetScaleFactor( out             int factor );\n        int  CanReceiveInput( out            bool canReceiveInput );\n        int  GetCompatibilityPolicyType( out APPLICATION_VIEW_COMPATIBILITY_POLICY flags );\n        int  SetCompatibilityPolicyType( APPLICATION_VIEW_COMPATIBILITY_POLICY flags );\n        int  GetSizeConstraints( IntPtr /* IImmersiveMonitor* */ monitor, out Size size1, out Size size2 );\n        int  GetSizeConstraintsForDpi( uint uint1, out Size size1, out Size size2 );\n        int  SetSizeConstraintsForDpi( ref uint uint1, ref Size size1, ref Size size2 );\n        int  OnMinSizePreferencesUpdated( IntPtr hWnd );\n        int  ApplyOperation( IntPtr /* IApplicationViewOperation* */ operation );\n        int  IsTray( out                  bool isTray );\n        int  IsInHighZOrderBand( out      bool isInHighZOrderBand );\n        int  IsSplashScreenPresented( out bool isSplashScreenPresented );\n        int  Flash();\n        int  GetRootSwitchableOwner( out                              IApplicationView rootSwitchableOwner );\n        int  EnumerateOwnershipTree( out                              IObjectArray     ownershipTree );\n        int  GetEnterpriseId( [MarshalAs( UnmanagedType.LPWStr )] out string           enterpriseId );\n        int  IsMirrored( out                                          bool             isMirrored );\n        int  Unknown1( out                                            int              unknown );\n        int  Unknown2( out                                            int              unknown );\n        int  Unknown3( out                                            int              unknown );\n        int  Unknown4( out                                            int              unknown );\n        int  Unknown5( out                                            int              unknown );\n        int  Unknown6( int                                                             unknown );\n        int  Unknown7();\n        int  Unknown8( out int   unknown );\n        int  Unknown9( int       unknown );\n        int  Unknown10( int      unknownX, int unknownY );\n        int  Unknown11( int      unknown );\n        int  Unknown12( out Size size1 );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"1841C6D7-4F9D-42C0-AF41-8747538F10E5\" )]\n    public interface IApplicationViewCollection\n    {\n        int  GetViews( out         IObjectArray array );\n        int  GetViewsByZOrder( out IObjectArray array );\n        int  GetViewsByAppUserModelId( string   id,          out IObjectArray     array );\n        int  GetViewForHWnd( IntPtr             hWnd,        out IApplicationView view );\n        int  GetViewForApplication( object      application, out IApplicationView view );\n        int  GetViewForAppUserModelId( string   id,          out IApplicationView view );\n        int  GetViewInFocus( out IntPtr         view );\n        int  Unknown1( out       IntPtr         view );\n        void RefreshCollection();\n        int  RegisterForApplicationViewChanges( object listener, out int cookie );\n        int  UnregisterForApplicationViewChanges( int  cookie );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"3F07F4BE-B107-441A-AF0F-39D82529072C\" )]\n    public interface IVirtualDesktop\n    {\n        bool IsViewVisible( IApplicationView view );\n        Guid GetId();\n\n#if NET5_0_OR_GREATER\n        public void GetString( out IntPtr hstr );\n#else\n        [return: MarshalAs( UnmanagedType.HString )]\n        string GetName();\n#endif\n\n        [return: MarshalAs( UnmanagedType.HString )]\n        string GetWallpaperPath();\n\n        bool IsRemote();\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"53F5CA0B-158F-4124-900C-057158060B27\" )]\n    internal interface IVirtualDesktopManagerInternal\n    {\n        int             GetCount();\n        void            MoveViewToDesktop( IApplicationView   view, IVirtualDesktop desktop );\n        bool            CanViewMoveDesktops( IApplicationView view );\n        IVirtualDesktop GetCurrentDesktop();\n        void            GetDesktops( out IObjectArray desktops );\n\n        [PreserveSig]\n        int GetAdjacentDesktop( IVirtualDesktop from, int direction, out IVirtualDesktop desktop );\n\n        void            SwitchDesktop( IVirtualDesktop desktop );\n        IVirtualDesktop CreateDesktop();\n        void            MoveDesktop( IVirtualDesktop                         desktop, int             nIndex );\n        void            RemoveDesktop( IVirtualDesktop                       desktop, IVirtualDesktop fallback );\n        IVirtualDesktop FindDesktop( ref Guid                                desktopId );\n        void            GetDesktopSwitchIncludeExcludeViews( IVirtualDesktop desktop, out IObjectArray unknown1, out IObjectArray unknown2 );\n#if NET5_0_OR_GREATER\n        void SetName( IVirtualDesktop      desktop, IntPtr newName );\n        void SetWallpaper( IVirtualDesktop desktop, IntPtr path );\n#else\n        void SetDesktopName( IVirtualDesktop      desktop, [MarshalAs( UnmanagedType.HString )] string name );\n        void SetDesktopWallpaper( IVirtualDesktop desktop, [MarshalAs( UnmanagedType.HString )] string path );\n#endif\n        void UpdateWallpaperPathForAllDesktops( [MarshalAs( UnmanagedType.HString )] string path );\n        void CopyDesktopState( IApplicationView                                             pView0, IApplicationView    pView1 );\n        void CreateRemoteDesktop( [MarshalAs( UnmanagedType.HString )] string               path,   out IVirtualDesktop desktop );\n        void SwitchRemoteDesktop( IVirtualDesktop                                           desktop );\n        void SwitchDesktopWithAnimation( IVirtualDesktop                                    desktop );\n        void GetLastActiveDesktop( out IVirtualDesktop                                      desktop );\n        void WaitForAnimationToComplete();\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"A5CD92FF-29BE-454C-8D04-D82879FB3F1B\" )]\n    internal interface IVirtualDesktopManager\n    {\n        bool IsWindowOnCurrentVirtualDesktop( IntPtr topLevelWindow );\n        Guid GetWindowDesktopId( IntPtr              topLevelWindow );\n        void MoveWindowToDesktop( IntPtr             topLevelWindow, ref Guid desktopId );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"4CE81583-1E4C-4632-A621-07A53543148F\" )]\n    internal interface IVirtualDesktopPinnedApps\n    {\n        bool IsAppIdPinned( string          appId );\n        void PinAppID( string               appId );\n        void UnpinAppID( string             appId );\n        bool IsViewPinned( IApplicationView applicationView );\n        void PinView( IApplicationView      applicationView );\n        void UnpinView( IApplicationView    applicationView );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"92CA9DCD-5622-4BBA-A805-5E9F541BD8C9\" )]\n    public interface IObjectArray\n    {\n        void GetCount( out int count );\n        void GetAt( int        index, ref Guid iid, [MarshalAs( UnmanagedType.Interface )] out object obj );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"6D5140C1-7436-11CE-8034-00AA006009FA\" )]\n    internal interface IServiceProvider10\n    {\n        [return: MarshalAs( UnmanagedType.IUnknown )]\n        object QueryService( ref Guid service, ref Guid riid );\n    }\n\n    [ComImport]\n    [Guid( \"B9E5E94D-233E-49AB-AF5C-2B4541C3AADE\" )]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    public interface IVirtualDesktopNotification\n    {\n        void VirtualDesktopCreated( IVirtualDesktop       pDesktop );\n        void VirtualDesktopDestroyBegin( IVirtualDesktop  pDesktopDestroyed, IVirtualDesktop pDesktopFallback );\n        void VirtualDesktopDestroyFailed( IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback );\n        void VirtualDesktopDestroyed( IVirtualDesktop     pDesktopDestroyed, IVirtualDesktop pDesktopFallback );\n        void VirtualDesktopMoved( IVirtualDesktop         pDesktop,          int             nIndexFrom, int nIndexTo );\n#if NET5_0_OR_GREATER\n        void VirtualDesktopRenamed( IVirtualDesktop pDesktop, IntPtr newName );\n#else\n        void VirtualDesktopRenamed( IVirtualDesktop pDesktop, [MarshalAs( UnmanagedType.HString )] string chName );\n#endif\n        void ViewVirtualDesktopChanged( IApplicationView   pView );\n        void CurrentVirtualDesktopChanged( IVirtualDesktop pDesktopOld, IVirtualDesktop pDesktopNew );\n\n#if NET5_0_OR_GREATER\n        void VirtualDesktopWallpaperChanged( IVirtualDesktop pDesktop, IntPtr newPath );\n#else\n        void VirtualDesktopWallpaperChanged( IVirtualDesktop pDesktop, [MarshalAs( UnmanagedType.HString )] string chPath );\n#endif\n        void VirtualDesktopSwitched( IVirtualDesktop        pDesktop );\n        void RemoteVirtualDesktopConnected( IVirtualDesktop pDesktop );\n    }\n\n    [ComImport]\n    [Guid( \"0cd45e71-d927-4f15-8b0a-8fef525337bf\" )]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    public interface IVirtualDesktopNotificationService\n    {\n        uint Register( IVirtualDesktopNotification pNotification );\n        void Unregister( uint                      dwCookie );\n    }\n}"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop11_23H2_3085/VirtualDesktop.cs",
    "content": "// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Diagnostics;\nusing System.Runtime.InteropServices;\nusing VirtualSpace;\n#if NET5_0_OR_GREATER\nusing WinRT;\n#endif\n\nnamespace VirtualDesktop\n{\n    public class Desktop : IDesktop\n    {\n        private readonly IVirtualDesktop _ivd;\n\n        private Desktop( IVirtualDesktop desktop )\n        {\n            _ivd = desktop;\n        }\n\n        public Guid Guid => _ivd.GetId();\n\n        public static int Count =>\n            // return the number of desktops\n            DesktopManager.GetDesktopCount();\n\n        public static Desktop Current\n        {\n            get\n            {\n                // returns current desktop\n                try\n                {\n                    return new Desktop( DesktopManager.VirtualDesktopManagerInternal.GetCurrentDesktop() );\n                }\n                catch\n                {\n                    DesktopManager.ResetDesktopManager();\n                    return new Desktop( DesktopManager.VirtualDesktopManagerInternal.GetCurrentDesktop() );\n                }\n            }\n        }\n\n        public bool IsVisible =>\n            // return true if this desktop is the current displayed one\n            ReferenceEquals( _ivd, DesktopManager.VirtualDesktopManagerInternal.GetCurrentDesktop() );\n\n        public Desktop Left\n        {\n            // return desktop at the left of this one, null if none\n            get\n            {\n                var hr = DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 3, out var desktop ); // 3 = LeftDirection\n                if ( hr == 0 )\n                    return new Desktop( desktop );\n                else\n                    return null;\n            }\n        }\n\n        public Desktop Right\n        {\n            // return desktop at the right of this one, null if none\n            get\n            {\n                var hr = DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 4, out var desktop ); // 4 = RightDirection\n                if ( hr == 0 )\n                    return new Desktop( desktop );\n                else\n                    return null;\n            }\n        }\n\n        // get process id to window handle\n        [DllImport( \"user32.dll\" )]\n        private static extern int GetWindowThreadProcessId( IntPtr hWnd, out int lpdwProcessId );\n\n        // get handle of active window\n        [DllImport( \"user32.dll\" )]\n        private static extern IntPtr GetForegroundWindow();\n\n        public override int GetHashCode()\n        {\n            // get hash\n            return _ivd.GetHashCode();\n        }\n\n        public override bool Equals( object? obj )\n        {\n            // compare with object\n            return obj is Desktop desk && ReferenceEquals( _ivd, desk._ivd );\n        }\n\n        public static Desktop FromIndex( int index )\n        {\n            // return desktop object from index (-> index = 0..Count-1)\n            return new Desktop( DesktopManager.GetDesktop( index ) );\n        }\n\n        public static Desktop FromWindow( IntPtr hWnd )\n        {\n            // return desktop object to desktop on which window <hWnd> is displayed\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var id = DesktopManager.VirtualDesktopManager.GetWindowDesktopId( hWnd );\n            return new Desktop( DesktopManager.VirtualDesktopManagerInternal.FindDesktop( ref id ) );\n        }\n\n        public static int SysIndexFromDesktop( Desktop desktop )\n        {\n            // return index of desktop object or -1 if not found\n            if ( desktop == null ) return -1;\n            return DesktopManager.GetDesktopIndex( desktop._ivd );\n        }\n\n        public static string DesktopNameFromDesktop( Desktop desktop )\n        {\n            // return name of desktop or \"Desktop n\" if it has no name\n\n            // get desktop name\n            string desktopName = null;\n            try\n            {\n#if NET5_0_OR_GREATER\n                desktop._ivd.GetString( out var hstr );\n                desktopName = MarshalString.FromAbi( hstr );\n#else\n                desktopName = desktop._ivd.GetName();\n#endif\n            }\n            catch ( Exception )\n            {\n            }\n\n            // no name found, generate generic name\n            if ( string.IsNullOrEmpty( desktopName ) )\n            {\n                // create name \"Desktop n\" (n = number starting with 1)\n                desktopName = \"Desktop \" + ( DesktopManager.GetDesktopIndex( desktop._ivd ) + 1 ).ToString();\n            }\n\n            return desktopName;\n        }\n\n        public static string DesktopNameFromIndex( int index )\n        {\n            // return name of desktop from index (-> index = 0..Count-1) or \"Desktop n\" if it has no name\n\n            // get desktop name\n            string desktopName = null;\n            try\n            {\n#if NET5_0_OR_GREATER\n                DesktopManager.GetDesktop( index ).GetString( out var hstr );\n                desktopName = MarshalString.FromAbi( hstr );\n#else\n                desktopName = DesktopManager.GetDesktop( index ).GetName();\n#endif\n            }\n            catch\n            {\n            }\n\n            // no name found, generate generic name\n            if ( string.IsNullOrEmpty( desktopName ) )\n            {\n                // create name \"Desktop n\" (n = number starting with 1)\n                desktopName = \"Desktop \" + ( index + 1 ).ToString();\n            }\n\n            return desktopName;\n        }\n\n        public static bool HasDesktopNameFromIndex( int index )\n        {\n            // return true is desktop is named or false if it has no name\n\n            // read desktop name in registry\n            string desktopName = null;\n            try\n            {\n#if NET5_0_OR_GREATER\n                DesktopManager.GetDesktop( index ).GetString( out var hstr );\n                desktopName = MarshalString.FromAbi( hstr );\n#else\n                desktopName = DesktopManager.GetDesktop( index ).GetName();\n#endif\n            }\n            catch\n            {\n            }\n\n            // name found?\n            if ( string.IsNullOrEmpty( desktopName ) )\n                return false;\n            else\n                return true;\n        }\n\n        public static string DesktopWallpaperFromIndex( int index )\n        {\n            // return name of desktop wallpaper from index (-> index = 0..Count-1)\n\n            // get desktop name\n            var desktopWpPath = \"\";\n            try\n            {\n                desktopWpPath = DesktopManager.GetDesktop( index ).GetWallpaperPath();\n            }\n            catch\n            {\n            }\n\n            return desktopWpPath;\n        }\n\n        public static int SearchDesktop( string partialName )\n        {\n            // get index of desktop with partial name, return -1 if no desktop found\n            var index = -1;\n\n            for ( var i = 0; i < DesktopManager.GetDesktopCount(); i++ )\n            {\n                // loop through all virtual desktops and compare partial name to desktop name\n                if ( DesktopNameFromIndex( i ).ToUpper().IndexOf( partialName.ToUpper() ) >= 0 )\n                {\n                    index = i;\n                    break;\n                }\n            }\n\n            return index;\n        }\n\n        public static Desktop Create()\n        {\n            // create a new desktop\n            return new Desktop( DesktopManager.VirtualDesktopManagerInternal.CreateDesktop() );\n        }\n\n        public void Remove( Desktop? fallback = null )\n        {\n            // destroy desktop and switch to <fallback>\n            IVirtualDesktop fallbackDesktop;\n            if ( fallback == null )\n            {\n                // if no fallback is given use desktop to the left except for desktop 0.\n                var dtToCheck = new Desktop( DesktopManager.GetDesktop( 0 ) );\n                if ( Equals( dtToCheck ) )\n                {\n                    // desktop 0: set fallback to second desktop (= \"right\" desktop)\n                    DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 4, out fallbackDesktop ); // 4 = RightDirection\n                }\n                else\n                {\n                    // set fallback to \"left\" desktop\n                    DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 3, out fallbackDesktop ); // 3 = LeftDirection\n                }\n            }\n            else\n                // set fallback desktop\n                fallbackDesktop = fallback._ivd;\n\n            DesktopManager.VirtualDesktopManagerInternal.RemoveDesktop( _ivd, fallbackDesktop );\n        }\n\n        public static void RemoveAll()\n        {\n            // remove all desktops but visible\n            // DesktopManager.VirtualDesktopManagerInternal.SetDesktopIsPerMonitor( true );\n        }\n\n        public void Move( int index )\n        {\n            // move current desktop to desktop in index (-> index = 0..Count-1)\n            DesktopManager.VirtualDesktopManagerInternal.MoveDesktop( _ivd, index );\n        }\n\n        public void SetName( string name )\n        {\n            // set name for desktop, empty string removes name\n#if NET5_0_OR_GREATER\n            var newName = MarshalString.CreateMarshaler( name );\n            DesktopManager.VirtualDesktopManagerInternal.SetName( _ivd, MarshalString.GetAbi( newName ) );\n#else\n            DesktopManager.VirtualDesktopManagerInternal.SetDesktopName( _ivd, name );\n#endif\n        }\n\n        public void SetWallpaperPath( string path )\n        {\n            // set path for wallpaper, empty string removes path\n            if ( string.IsNullOrEmpty( path ) ) throw new ArgumentNullException();\n\n#if NET5_0_OR_GREATER\n            var newPath = MarshalString.CreateMarshaler( path );\n            DesktopManager.VirtualDesktopManagerInternal.SetWallpaper( _ivd, MarshalString.GetAbi( newPath ) );\n#else\n            DesktopManager.VirtualDesktopManagerInternal.SetDesktopWallpaper( _ivd, path );\n#endif\n        }\n\n        public static void SetAllWallpaperPaths( string path )\n        {\n            // set wallpaper path for all desktops\n            if ( string.IsNullOrEmpty( path ) ) throw new ArgumentNullException();\n            DesktopManager.VirtualDesktopManagerInternal.UpdateWallpaperPathForAllDesktops( path );\n        }\n\n        public void MakeVisible()\n        {\n            // make this desktop visible\n            DesktopManager.VirtualDesktopManagerInternal.SwitchDesktop( _ivd );\n        }\n\n        public void MoveWindow( IntPtr hWnd )\n        {\n            // move window to this desktop\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            _ = GetWindowThreadProcessId( hWnd, out var processId );\n\n            if ( Process.GetCurrentProcess().Id == processId )\n            {\n                // window of process\n                try // the easy way (if we are owner)\n                {\n                    DesktopManager.VirtualDesktopManager.MoveWindowToDesktop( hWnd, _ivd.GetId() );\n                }\n                catch // window of process, but we are not the owner\n                {\n                    DesktopManager.ApplicationViewCollection.GetViewForHWnd( hWnd, out var view );\n                    DesktopManager.VirtualDesktopManagerInternal.MoveViewToDesktop( view, _ivd );\n                }\n            }\n            else\n            {\n                // window of other process\n                DesktopManager.ApplicationViewCollection.GetViewForHWnd( hWnd, out var view );\n                try\n                {\n                    DesktopManager.VirtualDesktopManagerInternal.MoveViewToDesktop( view, _ivd );\n                }\n                catch\n                {\n                    // could not move active window, try main window (or whatever windows thinks is the main window)\n                    DesktopManager.ApplicationViewCollection.GetViewForHWnd(\n                        Process.GetProcessById( processId ).MainWindowHandle,\n                        out view );\n                    DesktopManager.VirtualDesktopManagerInternal.MoveViewToDesktop( view, _ivd );\n                }\n            }\n        }\n\n        public void MoveActiveWindow()\n        {\n            // move active window to this desktop\n            MoveWindow( GetForegroundWindow() );\n        }\n\n        public bool HasWindow( IntPtr hWnd )\n        {\n            // return true if window is on this desktop\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            return _ivd.GetId() == DesktopManager.VirtualDesktopManager.GetWindowDesktopId( hWnd );\n        }\n\n        public static bool IsWindowPinned( IntPtr hWnd )\n        {\n            // return true if window is pinned to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            return DesktopManager.VirtualDesktopPinnedApps.IsViewPinned( hWnd.GetApplicationView() );\n        }\n\n        public static void PinWindow( IntPtr hWnd )\n        {\n            // pin window to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var view = hWnd.GetApplicationView();\n            if ( !DesktopManager.VirtualDesktopPinnedApps.IsViewPinned( view ) )\n            {\n                // pin only if not already pinned\n                DesktopManager.VirtualDesktopPinnedApps.PinView( view );\n            }\n        }\n\n        public static void UnpinWindow( IntPtr hWnd )\n        {\n            // unpin window from all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var view = hWnd.GetApplicationView();\n            if ( DesktopManager.VirtualDesktopPinnedApps.IsViewPinned( view ) )\n            {\n                // unpin only if not already unpinned\n                DesktopManager.VirtualDesktopPinnedApps.UnpinView( view );\n            }\n        }\n\n        public static bool IsApplicationPinned( IntPtr hWnd )\n        {\n            // return true if application for window is pinned to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            return DesktopManager.VirtualDesktopPinnedApps.IsAppIdPinned( DesktopManager.GetAppId( hWnd ) );\n        }\n\n        public static void PinApplication( IntPtr hWnd )\n        {\n            // pin application for window to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var appId = DesktopManager.GetAppId( hWnd );\n            if ( !DesktopManager.VirtualDesktopPinnedApps.IsAppIdPinned( appId ) )\n            {\n                // pin only if not already pinned\n                DesktopManager.VirtualDesktopPinnedApps.PinAppID( appId );\n            }\n        }\n\n        public static void UnpinApplication( IntPtr hWnd )\n        {\n            // unpin application for window from all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var view  = hWnd.GetApplicationView();\n            var appId = DesktopManager.GetAppId( hWnd );\n            if ( DesktopManager.VirtualDesktopPinnedApps.IsAppIdPinned( appId ) )\n            {\n                // unpin only if pinned\n                DesktopManager.VirtualDesktopPinnedApps.UnpinAppID( appId );\n            }\n        }\n\n        public static Desktop? FromId( Guid guid )\n        {\n            try\n            {\n                return new Desktop( DesktopManager.VirtualDesktopManagerInternal.FindDesktop( ref guid ) );\n            }\n            catch\n            {\n                return null;\n            }\n        }\n    }\n}"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop11_23H2_3085/VirtualDesktop11_23H2_3085.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFrameworks>net6.0-windows</TargetFrameworks>\n        <Nullable>enable</Nullable>\n        <CsWinRTEnabled>false</CsWinRTEnabled>\n        <LangVersion>9</LangVersion>\n    </PropertyGroup>\n\n    <ItemGroup Condition=\" '$(TargetFramework)' == 'net5.0-windows' Or '$(TargetFramework)' == 'net6.0-windows' \">\n        <PackageReference Include=\"Microsoft.Windows.CsWinRT\" Version=\"1.4.1\"/>\n    </ItemGroup>\n\n    <ItemGroup>\n        <ProjectReference Include=\"..\\..\\Bridge\\Bridge.csproj\"/>\n    </ItemGroup>\n\n</Project>"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop11_23H2_3085/VirtualDesktopManager.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Runtime.InteropServices;\n#if NET5_0_OR_GREATER\nusing WinRT;\n#endif\n\nnamespace VirtualDesktop\n{\n    public static class DesktopManager\n    {\n        private static  DisposableNotification             _disposableNotification;\n        private static  IVirtualDesktopNotificationService VirtualDesktopNotificationService;\n        internal static IVirtualDesktopManagerInternal     VirtualDesktopManagerInternal;\n        internal static IVirtualDesktopManager             VirtualDesktopManager;\n        internal static IVirtualDesktopPinnedApps          VirtualDesktopPinnedApps;\n        public static   IApplicationViewCollection         ApplicationViewCollection;\n\n        static DesktopManager()\n        {\n            if ( Environment.OSVersion.Version is {Major: 10, Build: >= 22000} )\n                Init();\n        }\n\n        public static void ResetDesktopManager()\n        {\n            Init();\n        }\n\n        private static void Init()\n        {\n            var shell = (IServiceProvider10)Activator.CreateInstance( Type.GetTypeFromCLSID( Guids.CLSID_ImmersiveShell ) );\n\n            VirtualDesktopManager = (IVirtualDesktopManager)Activator.CreateInstance(\n                Type.GetTypeFromCLSID( Guids.CLSID_VirtualDesktopManager ) );\n\n            VirtualDesktopManagerInternal = (IVirtualDesktopManagerInternal)shell.QueryService(\n                Guids.CLSID_VirtualDesktopManagerInternal,\n                typeof( IVirtualDesktopManagerInternal ).GUID );\n            ApplicationViewCollection = (IApplicationViewCollection)shell.QueryService(\n                typeof( IApplicationViewCollection ).GUID,\n                typeof( IApplicationViewCollection ).GUID );\n            VirtualDesktopPinnedApps = (IVirtualDesktopPinnedApps)shell.QueryService(\n                Guids.CLSID_VirtualDesktopPinnedApps,\n                typeof( IVirtualDesktopPinnedApps ).GUID );\n            VirtualDesktopNotificationService = (IVirtualDesktopNotificationService)shell.QueryService(\n                Guids.CLSID_VirtualDesktopNotificationService,\n                typeof( IVirtualDesktopNotificationService ).GUID );\n\n            _disposableNotification = new DisposableNotification();\n            _disposableNotification.DwCookie = VirtualDesktopNotificationService.Register( new EventProxy() );\n        }\n\n        public static int GetDesktopCount()\n        {\n            try\n            {\n                return VirtualDesktopManagerInternal.GetCount();\n            }\n            catch\n            {\n                ResetDesktopManager();\n                return VirtualDesktopManagerInternal.GetCount();\n            }\n        }\n\n        public static IVirtualDesktop GetDesktop( int index )\n        {\n            // get desktop with index\n            var count = GetDesktopCount();\n            if ( index < 0 || index >= count ) throw new ArgumentOutOfRangeException( nameof( index ) );\n            VirtualDesktopManagerInternal.GetDesktops( out var desktops );\n            desktops.GetAt( index, typeof( IVirtualDesktop ).GUID, out var objDesktop );\n            Marshal.ReleaseComObject( desktops );\n            return (IVirtualDesktop)objDesktop;\n        }\n\n        internal static int GetDesktopIndex( IVirtualDesktop desktop )\n        {\n            // get index of desktop\n            var count    = GetDesktopCount();\n            var index    = -1;\n            var idSearch = desktop.GetId();\n            VirtualDesktopManagerInternal.GetDesktops( out var desktops );\n            for ( var i = 0; i < count; i++ )\n            {\n                desktops.GetAt( i, typeof( IVirtualDesktop ).GUID, out var objDesktop );\n                if ( idSearch.CompareTo( ( (IVirtualDesktop)objDesktop ).GetId() ) == 0 )\n                {\n                    index = i;\n                    break;\n                }\n            }\n\n            Marshal.ReleaseComObject( desktops );\n            return index;\n        }\n\n        internal static IApplicationView GetApplicationView( this IntPtr hWnd )\n        {\n            // get application view to window handle\n            ApplicationViewCollection.GetViewForHWnd( hWnd, out var view );\n            return view;\n        }\n\n        internal static string GetAppId( IntPtr hWnd )\n        {\n            // get Application ID to window handle\n            hWnd.GetApplicationView().GetAppUserModelId( out var appId );\n            return appId;\n        }\n\n        public static int GetViewCount()\n        {\n            ApplicationViewCollection.GetViews( out var objectArray );\n            objectArray.GetCount( out var count );\n            Marshal.ReleaseComObject( objectArray );\n            return count;\n        }\n\n        public static event EventHandler<IVirtualDesktop>?                         Created;\n        public static event EventHandler<VirtualDesktopDestroyEventArgs>?          DestroyBegin;\n        public static event EventHandler<VirtualDesktopDestroyEventArgs>?          DestroyFailed;\n        public static event EventHandler<VirtualDesktopDestroyEventArgs>?          Destroyed;\n        public static event EventHandler<VirtualDesktopChangedEventArgs>?          CurrentChanged;\n        public static event EventHandler<VirtualDesktopMovedEventArgs>?            Moved;\n        public static event EventHandler<VirtualDesktopRenamedEventArgs>?          Renamed;\n        public static event EventHandler<VirtualDesktopWallpaperChangedEventArgs>? WallpaperChanged;\n\n        private class DisposableNotification : IDisposable\n        {\n            private bool _isDisposed;\n            public  uint DwCookie { private get; set; }\n\n            public void Dispose()\n            {\n                if ( _isDisposed ) return;\n\n                VirtualDesktopNotificationService.Unregister( DwCookie );\n                _isDisposed = true;\n            }\n        }\n\n        private class EventProxy : IVirtualDesktopNotification\n        {\n            public void ViewVirtualDesktopChanged( IApplicationView pView )\n            {\n                // throw new NotImplementedException();\n            }\n\n            public void CurrentVirtualDesktopChanged( IVirtualDesktop pDesktopOld, IVirtualDesktop pDesktopNew )\n            {\n                CurrentChanged?.Invoke( this, new VirtualDesktopChangedEventArgs( pDesktopOld, pDesktopNew ) );\n            }\n\n            public void VirtualDesktopCreated( IVirtualDesktop pDesktop )\n            {\n                Created?.Invoke( this, pDesktop );\n            }\n\n            public void VirtualDesktopDestroyBegin( IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback )\n            {\n                DestroyBegin?.Invoke( this, new VirtualDesktopDestroyEventArgs( pDesktopDestroyed, pDesktopFallback ) );\n            }\n\n            public void VirtualDesktopDestroyFailed( IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback )\n            {\n                DestroyFailed?.Invoke( this, new VirtualDesktopDestroyEventArgs( pDesktopDestroyed, pDesktopFallback ) );\n            }\n\n            public void VirtualDesktopDestroyed( IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback )\n            {\n                Destroyed?.Invoke( this, new VirtualDesktopDestroyEventArgs( pDesktopDestroyed, pDesktopFallback ) );\n            }\n\n\n            public void VirtualDesktopMoved( IVirtualDesktop pDesktop, int nIndexFrom, int nIndexTo )\n            {\n                Moved?.Invoke( this, new VirtualDesktopMovedEventArgs( pDesktop, nIndexFrom, nIndexTo ) );\n            }\n\n#if NET5_0_OR_GREATER\n            public void VirtualDesktopRenamed( IVirtualDesktop pDesktop, IntPtr newName )\n            {\n                var name = MarshalString.FromAbi( newName );\n                Renamed?.Invoke( this, new VirtualDesktopRenamedEventArgs( pDesktop, name ) );\n            }\n#else\n            public void VirtualDesktopRenamed( IVirtualDesktop pDesktop, string chName )\n            {\n                Renamed?.Invoke( this, new VirtualDesktopRenamedEventArgs( pDesktop, chName ) );\n            }\n#endif\n\n#if NET5_0_OR_GREATER\n            public void VirtualDesktopWallpaperChanged( IVirtualDesktop pDesktop, IntPtr newPath )\n            {\n                var path = MarshalString.FromAbi( newPath );\n                WallpaperChanged?.Invoke( this, new VirtualDesktopWallpaperChangedEventArgs( pDesktop, path ) );\n            }\n#else\n            public void VirtualDesktopWallpaperChanged( IVirtualDesktop pDesktop, string chPath )\n            {\n                WallpaperChanged?.Invoke( this, new VirtualDesktopWallpaperChangedEventArgs( pDesktop, chPath ) );\n            }\n#endif\n            public void VirtualDesktopSwitched( IVirtualDesktop pDesktop )\n            {\n                // throw new NotImplementedException();\n            }\n\n            public void RemoteVirtualDesktopConnected( IVirtualDesktop pDesktop )\n            {\n                // throw new NotImplementedException();\n            }\n        }\n    }\n\n    public class VirtualDesktopRenamedEventArgs : EventArgs\n    {\n        public VirtualDesktopRenamedEventArgs( IVirtualDesktop desktop, string name )\n        {\n            Desktop = desktop;\n            Name = name;\n        }\n\n        public IVirtualDesktop Desktop { get; }\n        public string          Name    { get; }\n    }\n\n    public class VirtualDesktopWallpaperChangedEventArgs : EventArgs\n    {\n        public VirtualDesktopWallpaperChangedEventArgs( IVirtualDesktop desktop, string path )\n        {\n            Desktop = desktop;\n            Path = path;\n        }\n\n        public IVirtualDesktop Desktop { get; }\n        public string          Path    { get; }\n    }\n\n\n    public class VirtualDesktopChangedEventArgs : EventArgs\n    {\n        public VirtualDesktopChangedEventArgs( IVirtualDesktop oldDesktop, IVirtualDesktop newDesktop )\n        {\n            OldDesktop = oldDesktop;\n            NewDesktop = newDesktop;\n        }\n\n        public IVirtualDesktop OldDesktop { get; }\n        public IVirtualDesktop NewDesktop { get; }\n    }\n\n    public class VirtualDesktopMovedEventArgs : EventArgs\n    {\n        public VirtualDesktopMovedEventArgs( IVirtualDesktop desktop, int oldIndex, int newIndex )\n        {\n            Desktop = desktop;\n            OldIndex = oldIndex;\n            NewIndex = newIndex;\n        }\n\n        public IVirtualDesktop Desktop  { get; }\n        public int             OldIndex { get; }\n        public int             NewIndex { get; }\n    }\n\n    public class VirtualDesktopDestroyEventArgs : EventArgs\n    {\n        public VirtualDesktopDestroyEventArgs( IVirtualDesktop destroyed, IVirtualDesktop fallback )\n        {\n            Destroyed = destroyed;\n            Fallback = fallback;\n        }\n\n        public IVirtualDesktop Destroyed { get; }\n        public IVirtualDesktop Fallback  { get; }\n    }\n}"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop11_24H2/COM.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Runtime.InteropServices;\n\nnamespace VirtualDesktop\n{\n    internal static class Guids\n    {\n        public static readonly Guid CLSID_ImmersiveShell                    = new( \"C2F03A33-21F5-47FA-B4BB-156362A2F239\" );\n        public static readonly Guid CLSID_VirtualDesktopManagerInternal     = new( \"C5E0CDCA-7B6E-41B2-9FC4-D93975CC467B\" );\n        public static readonly Guid CLSID_VirtualDesktopManager             = new( \"AA509086-5CA9-4C25-8F95-589D3C07B48A\" );\n        public static readonly Guid CLSID_VirtualDesktopPinnedApps          = new( \"B5A399E7-1C87-46B8-88E9-FC5747B171BD\" );\n        public static readonly Guid CLSID_VirtualDesktopNotificationService = new( \"A501FDEC-4A09-464C-AE4E-1B9C21B84918\" );\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct Size\n    {\n        public int X;\n        public int Y;\n    }\n\n    [StructLayout( LayoutKind.Sequential )]\n    public struct Rect\n    {\n        public int Left;\n        public int Top;\n        public int Right;\n        public int Bottom;\n    }\n\n    public enum APPLICATION_VIEW_CLOAK_TYPE : int\n    {\n        AVCT_NONE            = 0,\n        AVCT_DEFAULT         = 1,\n        AVCT_VIRTUAL_DESKTOP = 2\n    }\n\n    public enum APPLICATION_VIEW_COMPATIBILITY_POLICY : int\n    {\n        AVCP_NONE                = 0,\n        AVCP_SMALL_SCREEN        = 1,\n        AVCP_TABLET_SMALL_SCREEN = 2,\n        AVCP_VERY_SMALL_SCREEN   = 3,\n        AVCP_HIGH_SCALE_FACTOR   = 4\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"372E1D3B-38D3-42E4-A15B-8AB2B178F513\" )]\n    public interface IApplicationView\n    {\n        void GetIIdsSlot();\n        void GetRuntimeClassNameSlot();\n        void GetTrustLevelSlot();\n        int  SetFocus();\n        int  SwitchTo();\n        int  TryInvokeBack( IntPtr /* IAsyncCallback* */ callback );\n        int  GetThumbnailWindow( out IntPtr hWnd );\n        int  GetMonitor( out         IntPtr /* IImmersiveMonitor */ immersiveMonitor );\n        int  GetVisibility( out      int visibility );\n        int  SetCloak( APPLICATION_VIEW_CLOAK_TYPE cloakType, int unknown );\n        int  GetPosition( ref Guid guid /* GUID for IApplicationViewPosition */, out IntPtr /* IApplicationViewPosition** */ position );\n        int  SetPosition( ref IntPtr /* IApplicationViewPosition* */ position );\n        int  InsertAfterWindow( IntPtr hWnd );\n        int  GetExtendedFramePosition( out                              Rect rect );\n        int  GetAppUserModelId( [MarshalAs( UnmanagedType.LPWStr )] out string id );\n        int  SetAppUserModelId( string id );\n        int  IsEqualByAppUserModelId( string id, out int result );\n        int  GetViewState( out uint state );\n        int  SetViewState( uint state );\n        int  GetNeediness( out               int neediness );\n        int  GetLastActivationTimestamp( out ulong timestamp );\n        int  SetLastActivationTimestamp( ulong timestamp );\n        int  GetVirtualDesktopId( out Guid guid );\n        int  SetVirtualDesktopId( ref Guid guid );\n        int  GetShowInSwitchers( out  int flag );\n        int  SetShowInSwitchers( int flag );\n        int  GetScaleFactor( out             int factor );\n        int  CanReceiveInput( out            bool canReceiveInput );\n        int  GetCompatibilityPolicyType( out APPLICATION_VIEW_COMPATIBILITY_POLICY flags );\n        int  SetCompatibilityPolicyType( APPLICATION_VIEW_COMPATIBILITY_POLICY flags );\n        int  GetSizeConstraints( IntPtr /* IImmersiveMonitor* */ monitor, out Size size1, out Size size2 );\n        int  GetSizeConstraintsForDpi( uint uint1, out Size size1, out Size size2 );\n        int  SetSizeConstraintsForDpi( ref uint uint1, ref Size size1, ref Size size2 );\n        int  OnMinSizePreferencesUpdated( IntPtr hWnd );\n        int  ApplyOperation( IntPtr /* IApplicationViewOperation* */ operation );\n        int  IsTray( out                  bool isTray );\n        int  IsInHighZOrderBand( out      bool isInHighZOrderBand );\n        int  IsSplashScreenPresented( out bool isSplashScreenPresented );\n        int  Flash();\n        int  GetRootSwitchableOwner( out                              IApplicationView rootSwitchableOwner );\n        int  EnumerateOwnershipTree( out                              IObjectArray     ownershipTree );\n        int  GetEnterpriseId( [MarshalAs( UnmanagedType.LPWStr )] out string           enterpriseId );\n        int  IsMirrored( out                                          bool             isMirrored );\n        int  Unknown1( out                                            int              unknown );\n        int  Unknown2( out                                            int              unknown );\n        int  Unknown3( out                                            int              unknown );\n        int  Unknown4( out                                            int              unknown );\n        int  Unknown5( out                                            int              unknown );\n        int  Unknown6( int                                                             unknown );\n        int  Unknown7();\n        int  Unknown8( out int   unknown );\n        int  Unknown9( int       unknown );\n        int  Unknown10( int      unknownX, int unknownY );\n        int  Unknown11( int      unknown );\n        int  Unknown12( out Size size1 );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"1841C6D7-4F9D-42C0-AF41-8747538F10E5\" )]\n    public interface IApplicationViewCollection\n    {\n        int  GetViews( out         IObjectArray array );\n        int  GetViewsByZOrder( out IObjectArray array );\n        int  GetViewsByAppUserModelId( string   id,          out IObjectArray     array );\n        int  GetViewForHWnd( IntPtr             hWnd,        out IApplicationView view );\n        int  GetViewForApplication( object      application, out IApplicationView view );\n        int  GetViewForAppUserModelId( string   id,          out IApplicationView view );\n        int  GetViewInFocus( out IntPtr         view );\n        int  Unknown1( out       IntPtr         view );\n        void RefreshCollection();\n        int  RegisterForApplicationViewChanges( object listener, out int cookie );\n        int  UnregisterForApplicationViewChanges( int  cookie );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"3F07F4BE-B107-441A-AF0F-39D82529072C\" )]\n    public interface IVirtualDesktop\n    {\n        bool IsViewVisible( IApplicationView view );\n        Guid GetId();\n\n#if NET5_0_OR_GREATER\n        public void GetString( out IntPtr hstr );\n#else\n        [return: MarshalAs( UnmanagedType.HString )]\n        string GetName();\n#endif\n\n        [return: MarshalAs( UnmanagedType.HString )]\n        string GetWallpaperPath();\n\n        bool IsRemote();\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"53F5CA0B-158F-4124-900C-057158060B27\" )]\n    internal interface IVirtualDesktopManagerInternal\n    {\n        int             GetCount();\n        void            MoveViewToDesktop( IApplicationView   view, IVirtualDesktop desktop );\n        bool            CanViewMoveDesktops( IApplicationView view );\n        IVirtualDesktop GetCurrentDesktop();\n        void            GetDesktops( out IObjectArray desktops );\n\n        [PreserveSig]\n        int GetAdjacentDesktop( IVirtualDesktop from, int direction, out IVirtualDesktop desktop );\n\n        void            SwitchDesktop( IVirtualDesktop                      desktop );\n        void            SwitchDesktopAndMoveForegroundView( IVirtualDesktop desktop );\n        IVirtualDesktop CreateDesktop();\n        void            MoveDesktop( IVirtualDesktop                         desktop, int             nIndex );\n        void            RemoveDesktop( IVirtualDesktop                       desktop, IVirtualDesktop fallback );\n        IVirtualDesktop FindDesktop( ref Guid                                desktopId );\n        void            GetDesktopSwitchIncludeExcludeViews( IVirtualDesktop desktop, out IObjectArray unknown1, out IObjectArray unknown2 );\n#if NET5_0_OR_GREATER\n        void SetName( IVirtualDesktop      desktop, IntPtr newName );\n        void SetWallpaper( IVirtualDesktop desktop, IntPtr path );\n#else\n        void SetDesktopName( IVirtualDesktop      desktop, [MarshalAs( UnmanagedType.HString )] string name );\n        void SetDesktopWallpaper( IVirtualDesktop desktop, [MarshalAs( UnmanagedType.HString )] string path );\n#endif\n        void UpdateWallpaperPathForAllDesktops( [MarshalAs( UnmanagedType.HString )] string path );\n        void CopyDesktopState( IApplicationView                                             pView0, IApplicationView    pView1 );\n        void CreateRemoteDesktop( [MarshalAs( UnmanagedType.HString )] string               path,   out IVirtualDesktop desktop );\n        void SwitchRemoteDesktop( IVirtualDesktop                                           desktop );\n        void SwitchDesktopWithAnimation( IVirtualDesktop                                    desktop );\n        void GetLastActiveDesktop( out IVirtualDesktop                                      desktop );\n        void WaitForAnimationToComplete();\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"A5CD92FF-29BE-454C-8D04-D82879FB3F1B\" )]\n    internal interface IVirtualDesktopManager\n    {\n        bool IsWindowOnCurrentVirtualDesktop( IntPtr topLevelWindow );\n        Guid GetWindowDesktopId( IntPtr              topLevelWindow );\n        void MoveWindowToDesktop( IntPtr             topLevelWindow, ref Guid desktopId );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"4CE81583-1E4C-4632-A621-07A53543148F\" )]\n    internal interface IVirtualDesktopPinnedApps\n    {\n        bool IsAppIdPinned( string          appId );\n        void PinAppID( string               appId );\n        void UnpinAppID( string             appId );\n        bool IsViewPinned( IApplicationView applicationView );\n        void PinView( IApplicationView      applicationView );\n        void UnpinView( IApplicationView    applicationView );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"92CA9DCD-5622-4BBA-A805-5E9F541BD8C9\" )]\n    public interface IObjectArray\n    {\n        void GetCount( out int count );\n        void GetAt( int        index, ref Guid iid, [MarshalAs( UnmanagedType.Interface )] out object obj );\n    }\n\n    [ComImport]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    [Guid( \"6D5140C1-7436-11CE-8034-00AA006009FA\" )]\n    internal interface IServiceProvider10\n    {\n        [return: MarshalAs( UnmanagedType.IUnknown )]\n        object QueryService( ref Guid service, ref Guid riid );\n    }\n\n    [ComImport]\n    [Guid( \"B9E5E94D-233E-49AB-AF5C-2B4541C3AADE\" )]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    public interface IVirtualDesktopNotification\n    {\n        void VirtualDesktopCreated( IVirtualDesktop       pDesktop );\n        void VirtualDesktopDestroyBegin( IVirtualDesktop  pDesktopDestroyed, IVirtualDesktop pDesktopFallback );\n        void VirtualDesktopDestroyFailed( IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback );\n        void VirtualDesktopDestroyed( IVirtualDesktop     pDesktopDestroyed, IVirtualDesktop pDesktopFallback );\n        void VirtualDesktopMoved( IVirtualDesktop         pDesktop,          int             nIndexFrom, int nIndexTo );\n#if NET5_0_OR_GREATER\n        void VirtualDesktopRenamed( IVirtualDesktop pDesktop, IntPtr newName );\n#else\n        void VirtualDesktopRenamed( IVirtualDesktop pDesktop, [MarshalAs( UnmanagedType.HString )] string chName );\n#endif\n        void ViewVirtualDesktopChanged( IApplicationView   pView );\n        void CurrentVirtualDesktopChanged( IVirtualDesktop pDesktopOld, IVirtualDesktop pDesktopNew );\n\n#if NET5_0_OR_GREATER\n        void VirtualDesktopWallpaperChanged( IVirtualDesktop pDesktop, IntPtr newPath );\n#else\n        void VirtualDesktopWallpaperChanged( IVirtualDesktop pDesktop, [MarshalAs( UnmanagedType.HString )] string chPath );\n#endif\n        void VirtualDesktopSwitched( IVirtualDesktop        pDesktop );\n        void RemoteVirtualDesktopConnected( IVirtualDesktop pDesktop );\n    }\n\n    [ComImport]\n    [Guid( \"0cd45e71-d927-4f15-8b0a-8fef525337bf\" )]\n    [InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]\n    public interface IVirtualDesktopNotificationService\n    {\n        uint Register( IVirtualDesktopNotification pNotification );\n        void Unregister( uint                      dwCookie );\n    }\n}"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop11_24H2/VirtualDesktop.cs",
    "content": "// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Diagnostics;\nusing System.Reflection;\nusing System.Runtime.InteropServices;\nusing VirtualSpace;\n#if NET5_0_OR_GREATER\nusing WinRT;\n#endif\n\nnamespace VirtualDesktop\n{\n    public class Desktop : IDesktop\n    {\n        private readonly IVirtualDesktop _ivd;\n\n        private Desktop( IVirtualDesktop desktop )\n        {\n            _ivd = desktop;\n        }\n\n        public Guid Guid => _ivd.GetId();\n\n        public static int Count =>\n            // return the number of desktops\n            DesktopManager.GetDesktopCount();\n\n        public static Desktop Current\n        {\n            get\n            {\n                // returns current desktop\n                try\n                {\n                    return new Desktop( DesktopManager.VirtualDesktopManagerInternal.GetCurrentDesktop() );\n                }\n                catch\n                {\n                    DesktopManager.ResetDesktopManager();\n                    return new Desktop( DesktopManager.VirtualDesktopManagerInternal.GetCurrentDesktop() );\n                }\n            }\n        }\n\n        public bool IsVisible =>\n            // return true if this desktop is the current displayed one\n            ReferenceEquals( _ivd, DesktopManager.VirtualDesktopManagerInternal.GetCurrentDesktop() );\n\n        public Desktop Left\n        {\n            // return desktop at the left of this one, null if none\n            get\n            {\n                var hr = DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 3, out var desktop ); // 3 = LeftDirection\n                if ( hr == 0 )\n                    return new Desktop( desktop );\n                else\n                    return null;\n            }\n        }\n\n        public Desktop Right\n        {\n            // return desktop at the right of this one, null if none\n            get\n            {\n                var hr = DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 4, out var desktop ); // 4 = RightDirection\n                if ( hr == 0 )\n                    return new Desktop( desktop );\n                else\n                    return null;\n            }\n        }\n\n        // get process id to window handle\n        [DllImport( \"user32.dll\" )]\n        private static extern int GetWindowThreadProcessId( IntPtr hWnd, out int lpdwProcessId );\n\n        // get handle of active window\n        [DllImport( \"user32.dll\" )]\n        private static extern IntPtr GetForegroundWindow();\n\n        public override int GetHashCode()\n        {\n            // get hash\n            return _ivd.GetHashCode();\n        }\n\n        public override bool Equals( object? obj )\n        {\n            // compare with object\n            return obj is Desktop desk && ReferenceEquals( _ivd, desk._ivd );\n        }\n\n        public static Desktop FromIndex( int index )\n        {\n            // return desktop object from index (-> index = 0..Count-1)\n            return new Desktop( DesktopManager.GetDesktop( index ) );\n        }\n\n        public static Desktop? FromWindow( IntPtr hWnd )\n        {\n            // return desktop object to desktop on which window <hWnd> is displayed\n            if ( hWnd == IntPtr.Zero ) return null;\n            var id = DesktopManager.VirtualDesktopManager.GetWindowDesktopId( hWnd );\n\n            return GetDesktopByGuid( id );\n        }\n\n        public static int SysIndexFromDesktop( Desktop desktop )\n        {\n            // return index of desktop object or -1 if not found\n            if ( desktop == null ) return -1;\n            return DesktopManager.GetDesktopIndex( desktop._ivd );\n        }\n\n        public static string DesktopNameFromDesktop( Desktop desktop )\n        {\n            // return name of desktop or \"Desktop n\" if it has no name\n\n            // get desktop name\n            string desktopName = null;\n            try\n            {\n#if NET5_0_OR_GREATER\n                desktop._ivd.GetString( out var hstr );\n                desktopName = MarshalString.FromAbi( hstr );\n#else\n                desktopName = desktop._ivd.GetName();\n#endif\n            }\n            catch ( Exception )\n            {\n            }\n\n            // no name found, generate generic name\n            if ( string.IsNullOrEmpty( desktopName ) )\n            {\n                // create name \"Desktop n\" (n = number starting with 1)\n                desktopName = \"Desktop \" + ( DesktopManager.GetDesktopIndex( desktop._ivd ) + 1 ).ToString();\n            }\n\n            return desktopName;\n        }\n\n        public static string DesktopNameFromIndex( int index )\n        {\n            // return name of desktop from index (-> index = 0..Count-1) or \"Desktop n\" if it has no name\n\n            // get desktop name\n            string desktopName = null;\n            try\n            {\n#if NET5_0_OR_GREATER\n                DesktopManager.GetDesktop( index ).GetString( out var hstr );\n                desktopName = MarshalString.FromAbi( hstr );\n#else\n                desktopName = DesktopManager.GetDesktop( index ).GetName();\n#endif\n            }\n            catch\n            {\n            }\n\n            // no name found, generate generic name\n            if ( string.IsNullOrEmpty( desktopName ) )\n            {\n                // create name \"Desktop n\" (n = number starting with 1)\n                desktopName = \"Desktop \" + ( index + 1 ).ToString();\n            }\n\n            return desktopName;\n        }\n\n        public static bool HasDesktopNameFromIndex( int index )\n        {\n            // return true is desktop is named or false if it has no name\n\n            // read desktop name in registry\n            string desktopName = null;\n            try\n            {\n#if NET5_0_OR_GREATER\n                DesktopManager.GetDesktop( index ).GetString( out var hstr );\n                desktopName = MarshalString.FromAbi( hstr );\n#else\n                desktopName = DesktopManager.GetDesktop( index ).GetName();\n#endif\n            }\n            catch\n            {\n            }\n\n            // name found?\n            if ( string.IsNullOrEmpty( desktopName ) )\n                return false;\n            else\n                return true;\n        }\n\n        public static string DesktopWallpaperFromIndex( int index )\n        {\n            // return name of desktop wallpaper from index (-> index = 0..Count-1)\n\n            // get desktop name\n            var desktopWpPath = \"\";\n            try\n            {\n                desktopWpPath = DesktopManager.GetDesktop( index ).GetWallpaperPath();\n            }\n            catch\n            {\n            }\n\n            return desktopWpPath;\n        }\n\n        public static int SearchDesktop( string partialName )\n        {\n            // get index of desktop with partial name, return -1 if no desktop found\n            var index = -1;\n\n            for ( var i = 0; i < DesktopManager.GetDesktopCount(); i++ )\n            {\n                // loop through all virtual desktops and compare partial name to desktop name\n                if ( DesktopNameFromIndex( i ).ToUpper().IndexOf( partialName.ToUpper() ) >= 0 )\n                {\n                    index = i;\n                    break;\n                }\n            }\n\n            return index;\n        }\n\n        public static Desktop Create()\n        {\n            // create a new desktop\n            return new Desktop( DesktopManager.VirtualDesktopManagerInternal.CreateDesktop() );\n        }\n\n        public void Remove( Desktop? fallback = null )\n        {\n            // destroy desktop and switch to <fallback>\n            IVirtualDesktop fallbackDesktop;\n            if ( fallback == null )\n            {\n                // if no fallback is given use desktop to the left except for desktop 0.\n                var dtToCheck = new Desktop( DesktopManager.GetDesktop( 0 ) );\n                if ( Equals( dtToCheck ) )\n                {\n                    // desktop 0: set fallback to second desktop (= \"right\" desktop)\n                    DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 4, out fallbackDesktop ); // 4 = RightDirection\n                }\n                else\n                {\n                    // set fallback to \"left\" desktop\n                    DesktopManager.VirtualDesktopManagerInternal.GetAdjacentDesktop( _ivd, 3, out fallbackDesktop ); // 3 = LeftDirection\n                }\n            }\n            else\n                // set fallback desktop\n                fallbackDesktop = fallback._ivd;\n\n            DesktopManager.VirtualDesktopManagerInternal.RemoveDesktop( _ivd, fallbackDesktop );\n        }\n\n        public static void RemoveAll()\n        {\n            // remove all desktops but visible\n            // DesktopManager.VirtualDesktopManagerInternal.SetDesktopIsPerMonitor( true );\n        }\n\n        public void Move( int index )\n        {\n            // move current desktop to desktop in index (-> index = 0..Count-1)\n            DesktopManager.VirtualDesktopManagerInternal.MoveDesktop( _ivd, index );\n        }\n\n        public void SetName( string name )\n        {\n            // set name for desktop, empty string removes name\n#if NET5_0_OR_GREATER\n            var newName = MarshalString.CreateMarshaler( name );\n            DesktopManager.VirtualDesktopManagerInternal.SetName( _ivd, MarshalString.GetAbi( newName ) );\n#else\n            DesktopManager.VirtualDesktopManagerInternal.SetDesktopName( _ivd, name );\n#endif\n        }\n\n        public void SetWallpaperPath( string path )\n        {\n            // set path for wallpaper, empty string removes path\n            if ( string.IsNullOrEmpty( path ) ) throw new ArgumentNullException();\n\n#if NET5_0_OR_GREATER\n            var newPath = MarshalString.CreateMarshaler( path );\n            DesktopManager.VirtualDesktopManagerInternal.SetWallpaper( _ivd, MarshalString.GetAbi( newPath ) );\n#else\n            DesktopManager.VirtualDesktopManagerInternal.SetDesktopWallpaper( _ivd, path );\n#endif\n        }\n\n        public static void SetAllWallpaperPaths( string path )\n        {\n            // set wallpaper path for all desktops\n            if ( string.IsNullOrEmpty( path ) ) throw new ArgumentNullException();\n            DesktopManager.VirtualDesktopManagerInternal.UpdateWallpaperPathForAllDesktops( path );\n        }\n\n        public void MakeVisible()\n        {\n            // make this desktop visible\n            DesktopManager.VirtualDesktopManagerInternal.SwitchDesktop( _ivd );\n        }\n\n        public void MoveWindow( IntPtr hWnd )\n        {\n            // move window to this desktop\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            _ = GetWindowThreadProcessId( hWnd, out var processId );\n\n            if ( Process.GetCurrentProcess().Id == processId )\n            {\n                // window of process\n                try // the easy way (if we are owner)\n                {\n                    DesktopManager.VirtualDesktopManager.MoveWindowToDesktop( hWnd, _ivd.GetId() );\n                }\n                catch // window of process, but we are not the owner\n                {\n                    DesktopManager.ApplicationViewCollection.GetViewForHWnd( hWnd, out var view );\n                    DesktopManager.VirtualDesktopManagerInternal.MoveViewToDesktop( view, _ivd );\n                }\n            }\n            else\n            {\n                // window of other process\n                DesktopManager.ApplicationViewCollection.GetViewForHWnd( hWnd, out var view );\n                try\n                {\n                    DesktopManager.VirtualDesktopManagerInternal.MoveViewToDesktop( view, _ivd );\n                }\n                catch\n                {\n                    // could not move active window, try main window (or whatever windows thinks is the main window)\n                    DesktopManager.ApplicationViewCollection.GetViewForHWnd(\n                        Process.GetProcessById( processId ).MainWindowHandle,\n                        out view );\n                    DesktopManager.VirtualDesktopManagerInternal.MoveViewToDesktop( view, _ivd );\n                }\n            }\n        }\n\n        public void MoveActiveWindow()\n        {\n            // move active window to this desktop\n            MoveWindow( GetForegroundWindow() );\n        }\n\n        public bool HasWindow( IntPtr hWnd )\n        {\n            // return true if window is on this desktop\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            return _ivd.GetId() == DesktopManager.VirtualDesktopManager.GetWindowDesktopId( hWnd );\n        }\n\n        public static bool IsWindowPinned( IntPtr hWnd )\n        {\n            // return true if window is pinned to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            return DesktopManager.VirtualDesktopPinnedApps.IsViewPinned( hWnd.GetApplicationView() );\n        }\n\n        public static void PinWindow( IntPtr hWnd )\n        {\n            // pin window to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var view = hWnd.GetApplicationView();\n            if ( !DesktopManager.VirtualDesktopPinnedApps.IsViewPinned( view ) )\n            {\n                // pin only if not already pinned\n                DesktopManager.VirtualDesktopPinnedApps.PinView( view );\n            }\n        }\n\n        public static void UnpinWindow( IntPtr hWnd )\n        {\n            // unpin window from all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var view = hWnd.GetApplicationView();\n            if ( DesktopManager.VirtualDesktopPinnedApps.IsViewPinned( view ) )\n            {\n                // unpin only if not already unpinned\n                DesktopManager.VirtualDesktopPinnedApps.UnpinView( view );\n            }\n        }\n\n        public static bool IsApplicationPinned( IntPtr hWnd )\n        {\n            // return true if application for window is pinned to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            return DesktopManager.VirtualDesktopPinnedApps.IsAppIdPinned( DesktopManager.GetAppId( hWnd ) );\n        }\n\n        public static void PinApplication( IntPtr hWnd )\n        {\n            // pin application for window to all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var appId = DesktopManager.GetAppId( hWnd );\n            if ( !DesktopManager.VirtualDesktopPinnedApps.IsAppIdPinned( appId ) )\n            {\n                // pin only if not already pinned\n                DesktopManager.VirtualDesktopPinnedApps.PinAppID( appId );\n            }\n        }\n\n        public static void UnpinApplication( IntPtr hWnd )\n        {\n            // unpin application for window from all desktops\n            if ( hWnd == IntPtr.Zero ) throw new ArgumentNullException();\n            var view  = hWnd.GetApplicationView();\n            var appId = DesktopManager.GetAppId( hWnd );\n            if ( DesktopManager.VirtualDesktopPinnedApps.IsAppIdPinned( appId ) )\n            {\n                // unpin only if pinned\n                DesktopManager.VirtualDesktopPinnedApps.UnpinAppID( appId );\n            }\n        }\n\n        public static Desktop? FromId( Guid guid )\n        {\n            return GetDesktopByGuid( guid );\n        }\n\n        private static Desktop? GetDesktopByGuid( Guid guid )\n        {\n            Desktop? desktop = null;\n\n            try\n            {\n                var count = DesktopManager.GetDesktopCount();\n                DesktopManager.VirtualDesktopManagerInternal.GetDesktops( out var desktops );\n\n                for ( var i = 0; i < count; i++ )\n                {\n                    desktops.GetAt( i, typeof( IVirtualDesktop ).GUID, out var objDesktop );\n                    if ( guid.CompareTo( ( (IVirtualDesktop)objDesktop ).GetId() ) != 0 ) continue;\n                    desktop = new Desktop( (IVirtualDesktop)objDesktop );\n                }\n\n                Marshal.ReleaseComObject( desktops );\n                return desktop;\n            }\n            catch\n            {\n                return desktop;\n            }\n        }\n    }\n}"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop11_24H2/VirtualDesktop11_24H2.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFrameworks>net6.0-windows</TargetFrameworks>\n        <Nullable>enable</Nullable>\n        <CsWinRTEnabled>false</CsWinRTEnabled>\n        <LangVersion>9</LangVersion>\n    </PropertyGroup>\n\n    <ItemGroup Condition=\" '$(TargetFramework)' == 'net5.0-windows' Or '$(TargetFramework)' == 'net6.0-windows' \">\n        <PackageReference Include=\"Microsoft.Windows.CsWinRT\" Version=\"1.4.1\"/>\n    </ItemGroup>\n\n    <ItemGroup>\n        <ProjectReference Include=\"..\\..\\Bridge\\Bridge.csproj\"/>\n    </ItemGroup>\n\n</Project>"
  },
  {
    "path": "VirtualDesktop/VirtualDesktop11_24H2/VirtualDesktopManager.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Runtime.InteropServices;\n#if NET5_0_OR_GREATER\nusing WinRT;\n#endif\n\nnamespace VirtualDesktop\n{\n    public static class DesktopManager\n    {\n        private static  DisposableNotification             _disposableNotification;\n        private static  IVirtualDesktopNotificationService VirtualDesktopNotificationService;\n        internal static IVirtualDesktopManagerInternal     VirtualDesktopManagerInternal;\n        internal static IVirtualDesktopManager             VirtualDesktopManager;\n        internal static IVirtualDesktopPinnedApps          VirtualDesktopPinnedApps;\n        public static   IApplicationViewCollection         ApplicationViewCollection;\n\n        static DesktopManager()\n        {\n            if ( Environment.OSVersion.Version is {Major: 10, Build: >= 22000} )\n                Init();\n        }\n\n        public static void ResetDesktopManager()\n        {\n            Init();\n        }\n\n        private static void Init()\n        {\n            var shell = (IServiceProvider10)Activator.CreateInstance( Type.GetTypeFromCLSID( Guids.CLSID_ImmersiveShell ) );\n\n            VirtualDesktopManager = (IVirtualDesktopManager)Activator.CreateInstance(\n                Type.GetTypeFromCLSID( Guids.CLSID_VirtualDesktopManager ) );\n\n            VirtualDesktopManagerInternal = (IVirtualDesktopManagerInternal)shell.QueryService(\n                Guids.CLSID_VirtualDesktopManagerInternal,\n                typeof( IVirtualDesktopManagerInternal ).GUID );\n            ApplicationViewCollection = (IApplicationViewCollection)shell.QueryService(\n                typeof( IApplicationViewCollection ).GUID,\n                typeof( IApplicationViewCollection ).GUID );\n            VirtualDesktopPinnedApps = (IVirtualDesktopPinnedApps)shell.QueryService(\n                Guids.CLSID_VirtualDesktopPinnedApps,\n                typeof( IVirtualDesktopPinnedApps ).GUID );\n            VirtualDesktopNotificationService = (IVirtualDesktopNotificationService)shell.QueryService(\n                Guids.CLSID_VirtualDesktopNotificationService,\n                typeof( IVirtualDesktopNotificationService ).GUID );\n\n            _disposableNotification = new DisposableNotification();\n            _disposableNotification.DwCookie = VirtualDesktopNotificationService.Register( new EventProxy() );\n        }\n\n        public static int GetDesktopCount()\n        {\n            try\n            {\n                return VirtualDesktopManagerInternal.GetCount();\n            }\n            catch\n            {\n                ResetDesktopManager();\n                return VirtualDesktopManagerInternal.GetCount();\n            }\n        }\n\n        public static IVirtualDesktop GetDesktop( int index )\n        {\n            // get desktop with index\n            var count = GetDesktopCount();\n            if ( index < 0 || index >= count ) throw new ArgumentOutOfRangeException( nameof( index ) );\n            VirtualDesktopManagerInternal.GetDesktops( out var desktops );\n            desktops.GetAt( index, typeof( IVirtualDesktop ).GUID, out var objDesktop );\n            Marshal.ReleaseComObject( desktops );\n            return (IVirtualDesktop)objDesktop;\n        }\n\n        internal static int GetDesktopIndex( IVirtualDesktop desktop )\n        {\n            // get index of desktop\n            var count    = GetDesktopCount();\n            var index    = -1;\n            var idSearch = desktop.GetId();\n            VirtualDesktopManagerInternal.GetDesktops( out var desktops );\n            for ( var i = 0; i < count; i++ )\n            {\n                desktops.GetAt( i, typeof( IVirtualDesktop ).GUID, out var objDesktop );\n                if ( idSearch.CompareTo( ( (IVirtualDesktop)objDesktop ).GetId() ) == 0 )\n                {\n                    index = i;\n                    break;\n                }\n            }\n\n            Marshal.ReleaseComObject( desktops );\n            return index;\n        }\n\n        internal static IApplicationView GetApplicationView( this IntPtr hWnd )\n        {\n            // get application view to window handle\n            ApplicationViewCollection.GetViewForHWnd( hWnd, out var view );\n            return view;\n        }\n\n        internal static string GetAppId( IntPtr hWnd )\n        {\n            // get Application ID to window handle\n            hWnd.GetApplicationView().GetAppUserModelId( out var appId );\n            return appId;\n        }\n\n        public static int GetViewCount()\n        {\n            ApplicationViewCollection.GetViews( out var objectArray );\n            objectArray.GetCount( out var count );\n            Marshal.ReleaseComObject( objectArray );\n            return count;\n        }\n\n        public static event EventHandler<IVirtualDesktop>?                         Created;\n        public static event EventHandler<VirtualDesktopDestroyEventArgs>?          DestroyBegin;\n        public static event EventHandler<VirtualDesktopDestroyEventArgs>?          DestroyFailed;\n        public static event EventHandler<VirtualDesktopDestroyEventArgs>?          Destroyed;\n        public static event EventHandler<VirtualDesktopChangedEventArgs>?          CurrentChanged;\n        public static event EventHandler<VirtualDesktopMovedEventArgs>?            Moved;\n        public static event EventHandler<VirtualDesktopRenamedEventArgs>?          Renamed;\n        public static event EventHandler<VirtualDesktopWallpaperChangedEventArgs>? WallpaperChanged;\n\n        private class DisposableNotification : IDisposable\n        {\n            private bool _isDisposed;\n            public  uint DwCookie { private get; set; }\n\n            public void Dispose()\n            {\n                if ( _isDisposed ) return;\n\n                VirtualDesktopNotificationService.Unregister( DwCookie );\n                _isDisposed = true;\n            }\n        }\n\n        private class EventProxy : IVirtualDesktopNotification\n        {\n            public void ViewVirtualDesktopChanged( IApplicationView pView )\n            {\n                // throw new NotImplementedException();\n            }\n\n            public void CurrentVirtualDesktopChanged( IVirtualDesktop pDesktopOld, IVirtualDesktop pDesktopNew )\n            {\n                CurrentChanged?.Invoke( this, new VirtualDesktopChangedEventArgs( pDesktopOld, pDesktopNew ) );\n            }\n\n            public void VirtualDesktopCreated( IVirtualDesktop pDesktop )\n            {\n                Created?.Invoke( this, pDesktop );\n            }\n\n            public void VirtualDesktopDestroyBegin( IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback )\n            {\n                DestroyBegin?.Invoke( this, new VirtualDesktopDestroyEventArgs( pDesktopDestroyed, pDesktopFallback ) );\n            }\n\n            public void VirtualDesktopDestroyFailed( IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback )\n            {\n                DestroyFailed?.Invoke( this, new VirtualDesktopDestroyEventArgs( pDesktopDestroyed, pDesktopFallback ) );\n            }\n\n            public void VirtualDesktopDestroyed( IVirtualDesktop pDesktopDestroyed, IVirtualDesktop pDesktopFallback )\n            {\n                Destroyed?.Invoke( this, new VirtualDesktopDestroyEventArgs( pDesktopDestroyed, pDesktopFallback ) );\n            }\n\n\n            public void VirtualDesktopMoved( IVirtualDesktop pDesktop, int nIndexFrom, int nIndexTo )\n            {\n                Moved?.Invoke( this, new VirtualDesktopMovedEventArgs( pDesktop, nIndexFrom, nIndexTo ) );\n            }\n\n#if NET5_0_OR_GREATER\n            public void VirtualDesktopRenamed( IVirtualDesktop pDesktop, IntPtr newName )\n            {\n                var name = MarshalString.FromAbi( newName );\n                Renamed?.Invoke( this, new VirtualDesktopRenamedEventArgs( pDesktop, name ) );\n            }\n#else\n            public void VirtualDesktopRenamed( IVirtualDesktop pDesktop, string chName )\n            {\n                Renamed?.Invoke( this, new VirtualDesktopRenamedEventArgs( pDesktop, chName ) );\n            }\n#endif\n\n#if NET5_0_OR_GREATER\n            public void VirtualDesktopWallpaperChanged( IVirtualDesktop pDesktop, IntPtr newPath )\n            {\n                var path = MarshalString.FromAbi( newPath );\n                WallpaperChanged?.Invoke( this, new VirtualDesktopWallpaperChangedEventArgs( pDesktop, path ) );\n            }\n#else\n            public void VirtualDesktopWallpaperChanged( IVirtualDesktop pDesktop, string chPath )\n            {\n                WallpaperChanged?.Invoke( this, new VirtualDesktopWallpaperChangedEventArgs( pDesktop, chPath ) );\n            }\n#endif\n            public void VirtualDesktopSwitched( IVirtualDesktop pDesktop )\n            {\n                // throw new NotImplementedException();\n            }\n\n            public void RemoteVirtualDesktopConnected( IVirtualDesktop pDesktop )\n            {\n                // throw new NotImplementedException();\n            }\n        }\n    }\n\n    public class VirtualDesktopRenamedEventArgs : EventArgs\n    {\n        public VirtualDesktopRenamedEventArgs( IVirtualDesktop desktop, string name )\n        {\n            Desktop = desktop;\n            Name = name;\n        }\n\n        public IVirtualDesktop Desktop { get; }\n        public string          Name    { get; }\n    }\n\n    public class VirtualDesktopWallpaperChangedEventArgs : EventArgs\n    {\n        public VirtualDesktopWallpaperChangedEventArgs( IVirtualDesktop desktop, string path )\n        {\n            Desktop = desktop;\n            Path = path;\n        }\n\n        public IVirtualDesktop Desktop { get; }\n        public string          Path    { get; }\n    }\n\n\n    public class VirtualDesktopChangedEventArgs : EventArgs\n    {\n        public VirtualDesktopChangedEventArgs( IVirtualDesktop oldDesktop, IVirtualDesktop newDesktop )\n        {\n            OldDesktop = oldDesktop;\n            NewDesktop = newDesktop;\n        }\n\n        public IVirtualDesktop OldDesktop { get; }\n        public IVirtualDesktop NewDesktop { get; }\n    }\n\n    public class VirtualDesktopMovedEventArgs : EventArgs\n    {\n        public VirtualDesktopMovedEventArgs( IVirtualDesktop desktop, int oldIndex, int newIndex )\n        {\n            Desktop = desktop;\n            OldIndex = oldIndex;\n            NewIndex = newIndex;\n        }\n\n        public IVirtualDesktop Desktop  { get; }\n        public int             OldIndex { get; }\n        public int             NewIndex { get; }\n    }\n\n    public class VirtualDesktopDestroyEventArgs : EventArgs\n    {\n        public VirtualDesktopDestroyEventArgs( IVirtualDesktop destroyed, IVirtualDesktop fallback )\n        {\n            Destroyed = destroyed;\n            Fallback = fallback;\n        }\n\n        public IVirtualDesktop Destroyed { get; }\n        public IVirtualDesktop Fallback  { get; }\n    }\n}"
  },
  {
    "path": "VirtualDesktopWrapper/DesktopManagerWrapper.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nextern alias VirtualDesktop10;\nextern alias VirtualDesktop11;\nusing VirtualSpace.Helpers;\n\nnamespace VirtualSpace.VirtualDesktop.Api\n{\n    public static partial class DesktopManagerWrapper\n    {\n        public static Guid GetIdByIndex( int index )\n        {\n            try\n            {\n                if ( SysInfo.IsWin10 )\n                {\n                    return VirtualDesktop10::VirtualDesktop.DesktopManager.GetDesktop( index ).GetId();\n                }\n\n                return VirtualDesktop11::VirtualDesktop.DesktopManager.GetDesktop( index ).GetId();\n            }\n            catch\n            {\n                return default;\n            }\n        }\n\n        public static int GetViewCount()\n        {\n            if ( SysInfo.IsWin10 )\n            {\n                return VirtualDesktop10::VirtualDesktop.DesktopManager.GetViewCount();\n            }\n\n            return VirtualDesktop11::VirtualDesktop.DesktopManager.GetViewCount();\n        }\n\n        public static void ResetDesktopManager()\n        {\n            if ( SysInfo.IsWin10 )\n            {\n                VirtualDesktop10::VirtualDesktop.DesktopManager.ResetDesktopManager();\n            }\n            else\n            {\n                VirtualDesktop11::VirtualDesktop.DesktopManager.ResetDesktopManager();\n            }\n        }\n    }\n}"
  },
  {
    "path": "VirtualDesktopWrapper/DesktopManagerWrapper.events.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nextern alias VirtualDesktop10;\nextern alias VirtualDesktop11;\nusing System.Threading.Channels;\nusing VirtualSpace.Commons;\nusing VirtualSpace.Helpers;\nusing VD10 = VirtualDesktop10::VirtualDesktop;\nusing VD11 = VirtualDesktop11::VirtualDesktop;\n\nnamespace VirtualSpace.VirtualDesktop.Api\n{\n    public static partial class DesktopManagerWrapper\n    {\n        private static readonly Channel<VirtualDesktopNotification> VirtualDesktopNotifications = Channels.VirtualDesktopNotifications;\n\n        public static void RegisterVirtualDesktopEvents( WallpaperChanged wc10, Action<Guid, string> wc11 )\n        {\n            if ( SysInfo.IsWin10 )\n            {\n                RegisterVirtualDesktopEvents10( wc10 );\n            }\n            else\n            {\n                RegisterVirtualDesktopEvents11( wc11 );\n            }\n        }\n\n        private static void RegisterVirtualDesktopEvents10( WallpaperChanged wc )\n        {\n            VD10.DesktopManager.Created += ( _, e ) =>\n            {\n                VirtualDesktopNotifications.Writer.TryWrite( new VirtualDesktopNotification {Type = VirtualDesktopNotificationType.CREATED} );\n            };\n\n            VD10.DesktopManager.Destroyed += ( _, e ) =>\n            {\n                VirtualDesktopNotifications.Writer.TryWrite( new VirtualDesktopNotification\n                {\n                    Type = VirtualDesktopNotificationType.DELETED,\n                    NewId = e.Fallback.GetId()\n                } );\n            };\n\n            VD10.DesktopManager.CurrentChanged += ( _, e ) =>\n            {\n                VirtualDesktopNotifications.Writer.TryWrite( new VirtualDesktopNotification\n                {\n                    Type = VirtualDesktopNotificationType.CURRENT_CHANGED,\n                    NewId = e.NewDesktop.GetId(),\n                    OldId = e.OldDesktop.GetId()\n                } );\n            };\n\n            WatchWallpaperEvents( wc );\n        }\n\n        private static void RegisterVirtualDesktopEvents11( Action<Guid, string> wc11 )\n        {\n            VD11.DesktopManager.Created += ( _, e ) =>\n            {\n                VirtualDesktopNotifications.Writer.TryWrite( new VirtualDesktopNotification {Type = VirtualDesktopNotificationType.CREATED} );\n            };\n\n            VD11.DesktopManager.Destroyed += ( _, e ) =>\n            {\n                VirtualDesktopNotifications.Writer.TryWrite( new VirtualDesktopNotification\n                {\n                    Type = VirtualDesktopNotificationType.DELETED,\n                    NewId = e.Fallback.GetId()\n                } );\n            };\n\n            VD11.DesktopManager.CurrentChanged += ( _, e ) =>\n            {\n                VirtualDesktopNotifications.Writer.TryWrite( new VirtualDesktopNotification\n                {\n                    Type = VirtualDesktopNotificationType.CURRENT_CHANGED,\n                    NewId = e.NewDesktop.GetId(),\n                    OldId = e.OldDesktop.GetId()\n                } );\n            };\n\n            VD11.DesktopManager.WallpaperChanged += ( _, e ) =>\n            {\n                if ( string.IsNullOrEmpty( e.Path ) ) return;\n                wc11( e.Desktop.GetId(), e.Path );\n            };\n        }\n\n        public delegate void DesktopCreated();\n\n        public delegate void DesktopDeleted( VirtualDesktopNotification vdn );\n\n        public delegate void DesktopChanged( VirtualDesktopNotification vdn );\n\n        public static event DesktopCreated DesktopCreatedEvent;\n        public static event DesktopDeleted DesktopDeletedEvent;\n        public static event DesktopChanged DesktopChangedEvent;\n\n        public static async void ListenVirtualDesktopEvents()\n        {\n            while ( await VirtualDesktopNotifications.Reader.WaitToReadAsync() )\n            {\n                if ( VirtualDesktopNotifications.Reader.TryRead( out var vdn ) )\n                {\n                    switch ( vdn.Type )\n                    {\n                        case VirtualDesktopNotificationType.CREATED:\n                            DesktopCreatedEvent();\n\n                            break;\n                        case VirtualDesktopNotificationType.DELETED:\n                            DesktopDeletedEvent( vdn );\n\n                            break;\n                        case VirtualDesktopNotificationType.CURRENT_CHANGED:\n                            DesktopChangedEvent( vdn );\n\n                            break;\n                        default:\n                            throw new ArgumentOutOfRangeException();\n                    }\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "VirtualDesktopWrapper/DesktopManagerWrapper.wallpaper.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing Microsoft.Win32;\n\nnamespace VirtualSpace.VirtualDesktop.Api\n{\n    public static partial class DesktopManagerWrapper\n    {\n        public delegate void WallpaperChanged();\n\n        private const  string  WALLPAPER_REGISTRY_PREFIX = @\"HKEY_CURRENT_USER\\Control Panel\\Desktop\\\";\n        private const  string  COLOR_REGISTRY_PREFIX     = @\"HKEY_CURRENT_USER\\Control Panel\\Colors\\\";\n        private static string? _lastPath;\n        private static string? _lastColor;\n\n        private static void WatchWallpaperEvents( WallpaperChanged wc )\n        {\n            Task.Factory.StartNew( () =>\n            {\n                while ( true )\n                {\n                    var path  = Registry.GetValue( WALLPAPER_REGISTRY_PREFIX, \"Wallpaper\", \"\" ).ToString();\n                    var color = Registry.GetValue( COLOR_REGISTRY_PREFIX, \"Background\", \"\" ).ToString();\n\n                    if ( string.IsNullOrEmpty( _lastColor ) )\n                    {\n                        _lastPath = path;\n                        _lastColor = color;\n                    }\n\n                    if ( _lastPath != path || _lastColor != color )\n                    {\n                        _lastPath = path;\n                        _lastColor = color;\n                        wc();\n                    }\n\n                    Thread.Sleep( 1000 );\n                }\n            }, TaskCreationOptions.LongRunning );\n        }\n    }\n}"
  },
  {
    "path": "VirtualDesktopWrapper/DesktopWrapper.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nextern alias VirtualDesktop10;\nextern alias VirtualDesktop11;\nusing VirtualSpace.AppLogs;\nusing VirtualSpace.Helpers;\nusing VD10 = VirtualDesktop10::VirtualDesktop;\nusing VD11 = VirtualDesktop11::VirtualDesktop;\n\nnamespace VirtualSpace.VirtualDesktop.Api\n{\n    public static partial class DesktopWrapper\n    {\n        public delegate void OnDesktopVisible( IDesktop desktop, bool? forceFocusForegroundWindow = null );\n\n        public static int CurrentIndex => SysInfo.IsWin10 ? VD10.Desktop.SysIndexFromDesktop( VD10.Desktop.Current ) : VD11.Desktop.SysIndexFromDesktop( VD11.Desktop.Current );\n\n        public static int  Count       => SysInfo.IsWin10 ? VD10.Desktop.Count : VD11.Desktop.Count;\n        public static Guid CurrentGuid => SysInfo.IsWin10 ? VD10.Desktop.Current.Guid : VD11.Desktop.Current.Guid;\n\n        public static bool RemoveDesktopByGuid( Guid guid )\n        {\n            if ( Count <= 1 ) return false;\n            try\n            {\n                if ( SysInfo.IsWin10 )\n                {\n                    var desktop = VD10.Desktop.FromId( guid );\n                    desktop.Remove( null );\n                }\n                else\n                {\n                    var desktop = VD11.Desktop.FromId( guid );\n                    desktop.Remove( null );\n                }\n\n                return true;\n            }\n            catch ( Exception e )\n            {\n                Logger.Error( \"Remove Desktop: \" + e.Message );\n                return false;\n            }\n        }\n\n        public static void PinWindow( IntPtr handle, bool isPinned )\n        {\n            if ( SysInfo.IsWin10 )\n            {\n                if ( isPinned )\n                    VD10.Desktop.UnpinWindow( handle );\n                else\n                    VD10.Desktop.PinWindow( handle );\n            }\n            else\n            {\n                if ( isPinned )\n                    VD11.Desktop.UnpinWindow( handle );\n                else\n                    VD11.Desktop.PinWindow( handle );\n            }\n        }\n\n        public static void PinApp( IntPtr handle, bool isPinned )\n        {\n            if ( SysInfo.IsWin10 )\n            {\n                if ( isPinned )\n                    VD10.Desktop.UnpinApplication( handle );\n                else\n                    VD10.Desktop.PinApplication( handle );\n            }\n            else\n            {\n                if ( isPinned )\n                    VD11.Desktop.UnpinApplication( handle );\n                else\n                    VD11.Desktop.PinApplication( handle );\n            }\n        }\n\n        public static bool IsWindowPinned( IntPtr handle )\n        {\n            return SysInfo.IsWin10 ? VD10.Desktop.IsWindowPinned( handle ) : VD11.Desktop.IsWindowPinned( handle );\n        }\n\n        public static bool IsApplicationPinned( IntPtr handle )\n        {\n            return SysInfo.IsWin10 ? VD10.Desktop.IsApplicationPinned( handle ) : VD11.Desktop.IsApplicationPinned( handle );\n        }\n\n        public static string DesktopNameFromIndex( int sysIndex )\n        {\n            return SysInfo.IsWin10 ? VD10.Desktop.DesktopNameFromIndex( sysIndex ) : VD11.Desktop.DesktopNameFromIndex( sysIndex );\n        }\n\n        public static string DesktopNameFromGuid( Guid guid )\n        {\n            if ( SysInfo.IsWin10 )\n            {\n                var desktop = VD10.Desktop.FromId( guid );\n                return desktop == null ? \"\" : VD10.Desktop.DesktopNameFromDesktop( desktop );\n            }\n            else\n            {\n                var desktop = VD11.Desktop.FromId( guid );\n                return desktop == null ? \"\" : VD11.Desktop.DesktopNameFromDesktop( desktop );\n            }\n        }\n\n        public static int IndexFromGuid( Guid guid )\n        {\n            if ( SysInfo.IsWin10 )\n            {\n                var desktop = VD10.Desktop.FromId( guid );\n                return VD10.Desktop.SysIndexFromDesktop( desktop );\n            }\n            else\n            {\n                var desktop = VD11.Desktop.FromId( guid );\n                return VD11.Desktop.SysIndexFromDesktop( desktop );\n            }\n        }\n\n        public static void MoveWindowToDesktop( IntPtr handle, int sysIndex )\n        {\n            if ( SysInfo.IsWin10 )\n            {\n                var desktop = VD10.Desktop.FromIndex( sysIndex );\n                desktop.MoveWindow( handle );\n            }\n            else\n            {\n                var desktop = VD11.Desktop.FromIndex( sysIndex );\n                desktop.MoveWindow( handle );\n            }\n        }\n\n        public static void MakeVisibleByIndex( int sysIndex )\n        {\n            if ( SysInfo.IsWin10 )\n            {\n                VD10.Desktop.FromIndex( sysIndex ).MakeVisible();\n            }\n            else\n            {\n                VD11.Desktop.FromIndex( sysIndex ).MakeVisible();\n            }\n        }\n\n        public static void MakeVisibleByGuid( Guid guid, bool? forceFocusForegroundWindow = null )\n        {\n            IDesktop? desktop;\n\n            if ( SysInfo.IsWin10 )\n            {\n                desktop = VD10.Desktop.FromId( guid );\n            }\n            else\n            {\n                desktop = VD11.Desktop.FromId( guid );\n            }\n\n            if ( desktop is null ) return;\n\n            OnDesktopVisibleEvent( desktop, forceFocusForegroundWindow );\n        }\n\n        public static void SetNameByGuid( Guid guid, string name )\n        {\n            if ( SysInfo.IsWin10 )\n            {\n                VD10.Desktop.FromId( guid )?.SetName( name );\n            }\n            else\n            {\n                VD11.Desktop.FromId( guid )?.SetName( name );\n            }\n        }\n\n        public static Guid GuidFromWindow( IntPtr handle )\n        {\n            if ( SysInfo.IsWin10 )\n            {\n                var desktop10 = VD10.Desktop.FromWindow( handle );\n                return desktop10?.Guid ?? Guid.Empty;\n            }\n\n            var desktop11 = VD11.Desktop.FromWindow( handle );\n            return desktop11?.Guid ?? Guid.Empty;\n        }\n\n        public static event OnDesktopVisible OnDesktopVisibleEvent;\n    }\n}"
  },
  {
    "path": "VirtualDesktopWrapper/VirtualDesktopWrapper.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFramework>net6.0-windows</TargetFramework>\n        <ImplicitUsings>enable</ImplicitUsings>\n        <Nullable>enable</Nullable>\n    </PropertyGroup>\n\n    <ItemGroup>\n        <ProjectReference Include=\"..\\Helpers\\Helpers.csproj\"/>\n        <ProjectReference Include=\"..\\VirtualDesktop\\VirtualDesktop10\\VirtualDesktop10.csproj\">\n            <Aliases>VirtualDesktop10</Aliases>\n        </ProjectReference>\n        <ProjectReference Include=\"..\\VirtualDesktop\\VirtualDesktop11_24H2\\VirtualDesktop11_24H2.csproj\">\n            <Aliases>VirtualDesktop11</Aliases>\n        </ProjectReference>\n    </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "VirtualDesktopWrapper/Wrapper11.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nextern alias VirtualDesktop10;\nextern alias VirtualDesktop11;\nusing VirtualSpace.Helpers;\nusing VD10 = VirtualDesktop10::VirtualDesktop;\nusing VD11 = VirtualDesktop11::VirtualDesktop;\n\nnamespace VirtualSpace.VirtualDesktop.Api\n{\n    public static partial class DesktopWrapper\n    {\n        public static void Create()\n        {\n            if ( SysInfo.IsWin10 )\n            {\n                VD10.Desktop.Create();\n            }\n            else\n            {\n                var desk = VD11.Desktop.Create();\n                var path = WinRegistry.GetDefaultWallpaperPath();\n                if ( !string.IsNullOrEmpty( path ) )\n                    desk.SetWallpaperPath( path );\n            }\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/App.xaml",
    "content": "﻿<Application x:Class=\"VirtualSpace.App\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n    <Application.Resources>\n        \n    </Application.Resources>\n</Application>"
  },
  {
    "path": "VirtualSpace/App.xaml.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Linq;\nusing System.Reflection;\nusing System.Runtime.InteropServices;\nusing System.Threading;\nusing System.Windows;\nusing System.Windows.Forms;\nusing VirtualSpace.AppLogs;\nusing VirtualSpace.Commons;\nusing VirtualSpace.Config;\nusing VirtualSpace.Factory;\nusing VirtualSpace.Helpers;\nusing VirtualSpace.Plugin;\nusing VirtualSpace.Tools;\nusing VirtualSpace.VirtualDesktop;\nusing VirtualSpace.VirtualDesktop.Api;\nusing Application = System.Windows.Application;\nusing ConfigManager = VirtualSpace.Config.Manager;\nusing Point = System.Drawing.Point;\n\nnamespace VirtualSpace\n{\n    /// <summary>\n    ///     Interaction logic for App.xaml\n    /// </summary>\n    public partial class App : Application\n    {\n        private static Mutex? _mutex;\n        public         bool   HideOnStart;\n\n        protected override void OnStartup( StartupEventArgs e )\n        {\n            base.OnStartup( e );\n\n            LogManager.GorgeousDividingLine();\n\n            if ( SystemTool.VersionCheck() &&\n                 SingleInstanceCheck() &&\n                 ConfigManager.Init() )\n            {\n                Bootstrap();\n\n                if ( e.Args.Contains( Const.Args.HIDE_ON_START ) ) HideOnStart = true;\n\n                var mw = CreateCanvas( e );\n                Current.MainWindow = mw;\n\n                IpcPipeServer.MainWindowHandle = mw.Handle;\n\n                if ( ConfigManager.Configs.Cluster.HideOnStart || HideOnStart )\n                {\n                    mw.Left = Const.FakeHideX;\n                    mw.Top = Const.FakeHideY;\n                }\n\n                mw.Show();\n\n                if ( ConfigManager.Configs.Cluster.HideOnStart || HideOnStart )\n                {\n                    mw.FakeHide();\n                }\n\n                PluginHost.AutoStartAfterMainWindowLoaded();\n            }\n            else\n            {\n                Current.Shutdown();\n            }\n        }\n\n        protected override void OnExit( ExitEventArgs e )\n        {\n            base.OnExit( e );\n\n            ReleaseMutex();\n            IpcPipeServer.SimpleShutdown();\n        }\n\n        public void ReleaseMutex()\n        {\n            _mutex?.ReleaseMutex();\n            _mutex?.Dispose();\n            _mutex = null;\n        }\n\n        private static bool SingleInstanceCheck()\n        {\n            var createdNew = TryMutex();\n            if ( createdNew )\n            {\n                IpcPipeServer.Start();\n            }\n            else\n            {\n                IpcPipeServer.AsClient();\n            }\n\n            return createdNew;\n        }\n\n        public static bool TryMutex()\n        {\n            _mutex = new Mutex( true, \"乱花渐欲迷人眼\", out var createdNew );\n            return createdNew;\n        }\n\n        private MainWindow CreateCanvas( StartupEventArgs args )\n        {\n            var canvas = VirtualSpace.MainWindow.Create( AppControllerFactory.Create( mergedDictionaries: Resources.MergedDictionaries ) );\n            return canvas;\n        }\n\n        private static void Bootstrap()\n        {\n            Logger.ShowLogsInGui = ConfigManager.Configs.LogConfig.ShowLogsInGui;\n\n            BootInfo();\n\n            TrayIcon.Show();\n\n            Daemon.Start();\n\n            PluginHost.RegisterPlugins( ConfigManager.GetPluginsPath() );\n        }\n\n        private static void BootInfo()\n        {\n            var screen = Screen.FromPoint( new Point() );\n            var ar     = SysInfo.GetAspectRadioOfScreen();\n            Logger.Info( $\"Application Start Successfully: {ConfigManager.AppPath}\" );\n            LogForVersion();\n            Logger.Info( $\"System Version: {SysInfo.OSVersion}\" );\n            Logger.Info( $\".NET Runtime: {RuntimeInformation.FrameworkDescription}\" );\n            Logger.Info( $\"Total Screens: {Screen.AllScreens.Length}\" );\n            Logger.Info( $\"Total VirtualDesktops: {DesktopWrapper.Count}\" );\n            Logger.Info( $\"Start Screen: {screen.DeviceName} ({screen.DeviceFriendlyName()})\" );\n            Logger.Info( $\"Start Screen Aspect Ratio: [{ar.W}:{ar.H}]\" );\n            Logger.Info( $\"Start VirtualDesktop: Desktop[{DesktopWrapper.CurrentIndex}]\" );\n            Logger.Info( $\"Start Position: [{Screen.PrimaryScreen.Bounds.Location.X}, {Screen.PrimaryScreen.Bounds.Location.Y}]\" );\n            Logger.Info( $\"Start Size: {Screen.PrimaryScreen.Bounds.Width}*{Screen.PrimaryScreen.Bounds.Height}\" );\n            Logger.Info( $\"Is Running As Administrator: {SysInfo.IsAdministrator}\" );\n            Logger.Info( $\"Current Profile: {ConfigManager.Configs.CurrentProfileName}\" );\n            Logger.Info( $\"Language: {ConfigManager.CurrentProfile.UI.Language}\" );\n        }\n\n        private static void LogForVersion()\n        {\n            var version = string.Empty;\n            try\n            {\n                version = ( (AssemblyInformationalVersionAttribute)Attribute.GetCustomAttribute(\n                    Assembly.GetEntryAssembly(),\n                    typeof( AssemblyInformationalVersionAttribute ),\n                    false ) ).InformationalVersion;\n            }\n            catch\n            {\n                // ignored\n            }\n\n            if ( !string.IsNullOrEmpty( version ) ) Logger.Info( $\"Application Version: {version}\" );\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/AssemblyInfo.cs",
    "content": "using System.Windows;\n\n[assembly: ThemeInfo(\n    ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located\n    //(used if a resource is not found in the page,\n    // or application resource dictionaries)\n    ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located\n    //(used if a resource is not found in the page,\n    // app, or any theme specific resource dictionaries)\n)]"
  },
  {
    "path": "VirtualSpace/AutoVersion.tt",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\n<#@ template debug=\"false\" hostspecific=\"false\" language=\"C#\" #>\n<#@ output extension=\".cs\" #>\n\n<#@ Assembly Name=\"System.Core.dll\" #>\n<#@ import namespace=\"System.IO\" #>\n\nusing System.Reflection;\n\n[assembly: AssemblyProduct(\"<#= AppName #>\")]\n\n[assembly: AssemblyTitle(\"<#= AppDesc #>\")]\n[assembly: AssemblyDescription(\"<#= AppDesc #>\")]\n\n[assembly: AssemblyCompany(\"https://github.com/newlooper\")]\n\n[assembly: AssemblyCopyright(\"Copyright © <#= Copyright #>\")]\n\n[assembly: AssemblyVersion(\"<#= MAJOR #>.<#= MINOR #>.<#= DaysSinceProjectStarted #>.<#= MinutesSinceMidnight #>\")]\n[assembly: AssemblyFileVersion(\"<#= MAJOR #>.<#= MINOR #>.<#= DaysSinceProjectStarted #>.<#= MinutesSinceMidnight #>\")]\n[assembly: AssemblyInformationalVersion(\"<#= MAJOR #>.<#= MINOR #>.<#= DaysSinceProjectStarted #>.<#= MinutesSinceMidnight/*+\".\"+WinVer*/ #>\")]\n\n<#+\n    private static readonly DateTime ProjectStartedDate = new( 2021, 12, 5 );\n\n    private static readonly string Copyright = ProjectStartedDate.Year + \" - \" + DateTime.Now.Year;\n    private static readonly string AppName = new DirectoryInfo( \".\" ).Name;\n    private static readonly string AppDesc = \"VirtualSpace - Windows VirtualDesktop Enhancement\";\n\n        private const int MAJOR = 0;\n        private const int MINOR = 2;\n\n    private static readonly int DaysSinceProjectStarted = (int)( DateTime.UtcNow - ProjectStartedDate ).TotalDays;\n    private static readonly int MinutesSinceMidnight = (int)DateTime.UtcNow.TimeOfDay.TotalMinutes;\n    // private static readonly string WinVer = Environment.GetEnvironmentVariable(\"VirtualSpaceVersion\"); // set in ENV before run `dotnet publish`\n#>"
  },
  {
    "path": "VirtualSpace/COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "VirtualSpace/Factory/AppControllerFactory.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.Collections.ObjectModel;\nusing System.Windows;\n\nnamespace VirtualSpace.Factory\n{\n    public static class AppControllerFactory\n    {\n        public static IAppController Create( string name = \"WPF\", Collection<ResourceDictionary>? mergedDictionaries = null )\n        {\n            switch ( name )\n            {\n                case \"WinForm\":\n                    // return new AppController();\n                case \"WPF\":\n                    mergedDictionaries?.Add( ControlPanel.ExportResourceDictionary.Instance );\n                    var mw = new ControlPanel.MainWindow();\n                    mw.ForceLoad();\n                    return mw;\n                default:\n                    return null;\n            }\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/MainWindow.filter.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\n\nusing System.Windows;\nusing VirtualSpace.Config;\nusing VirtualSpace.VirtualDesktop;\n\nnamespace VirtualSpace\n{\n    public partial class MainWindow\n    {\n        private void ToggleWindowFilter()\n        {\n            if ( !IsShowing() ) return;\n\n            var filterRow = Canvas.RowDefinitions[1];\n            if ( filterRow.Height.Value == 0 )\n            {\n                filterRow.Height = new GridLength( Const.Window.WINDOW_FILTER_BAR_HEIGHT, GridUnitType.Pixel );\n                ShowFilterWindow();\n            }\n            else\n            {\n                filterRow.Height = new GridLength( 0 );\n                HideFilterWindow( clearKeyword: false );\n            }\n\n            UpdateLayout();\n            VirtualDesktopManager.ShowAllVirtualDesktops();\n        }\n\n        private void ShowFilterWindow()\n        {\n            var wf = WindowFilter.GetInstance( _instance.Handle );\n            wf.Width = Width;\n            wf.Left = Left;\n            wf.Top = Height - Const.Window.WINDOW_FILTER_BAR_HEIGHT;\n            wf.Show();\n            wf.SetFocus();\n        }\n\n        private static void HideFilterWindow( bool clearKeyword = true )\n        {\n            var filterRow = _instance.Canvas.RowDefinitions[1];\n            filterRow.Height = new GridLength( 0 );\n\n            var wf = WindowFilter.GetInstance( _instance.Handle );\n            wf.ClearAndHide( clearKeyword );\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/MainWindow.hotkeys.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Diagnostics;\nusing System.Runtime.InteropServices;\nusing System.Windows.Forms;\nusing System.Windows.Input;\nusing VirtualSpace.AppLogs;\nusing VirtualSpace.Config;\nusing VirtualSpace.Helpers;\nusing VirtualSpace.Tools;\nusing GHK = VirtualSpace.Helpers.GlobalHotKey;\nusing LLKH = VirtualSpace.Helpers.LowLevelKeyboardHook;\n\nnamespace VirtualSpace\n{\n    public partial class MainWindow\n    {\n        private static readonly Stopwatch RiseTaskViewTimer = Stopwatch.StartNew();\n        private static readonly Stopwatch DoublePressTimer  = Stopwatch.StartNew();\n\n        private void RegisterHotKey( IntPtr hWnd )\n        {\n            foreach ( var (k, kbInProfile) in Manager.Configs.KeyBindings! )\n            {\n                var ghkCode = kbInProfile.GhkCode;\n                if ( ghkCode == \"\" ) continue;\n\n                var func      = Const.Hotkey.GetFuncDesc( k );\n                var messageId = Const.Hotkey.GetKeyBinding( k ).MessageId;\n                var hotkeyStr = ghkCode.Replace( Const.Hotkey.NONE + Const.Hotkey.SPLITTER, \"\" );\n\n                var arr = ghkCode.Split( Const.Hotkey.SPLITTER );\n                if ( arr.Length == 5 )\n                {\n                    var km = arr[0] == Const.Hotkey.NONE ? GHK.KeyModifiers.None : GHK.KeyModifiers.WindowsKey;\n                    km |= arr[1] == Const.Hotkey.NONE ? GHK.KeyModifiers.None : GHK.KeyModifiers.Ctrl;\n                    km |= arr[2] == Const.Hotkey.NONE ? GHK.KeyModifiers.None : GHK.KeyModifiers.Alt;\n                    km |= arr[3] == Const.Hotkey.NONE ? GHK.KeyModifiers.None : GHK.KeyModifiers.Shift;\n\n                    try\n                    {\n                        var key = Enum.Parse<Key>( arr[4] );\n                        Logger.Info( string.Format( \"Register Global HotKey [{0}] For \\\"{1}\\\", {2}\",\n                            hotkeyStr,\n                            func,\n                            GHK.RegHotKey( hWnd, messageId, km, KeyInterop.VirtualKeyFromKey( key ) )\n                                ? \"Success\"\n                                : \"Fail\" ) );\n                    }\n                    catch ( Exception ex )\n                    {\n                        Logger.Error( string.Format( \"Register Global HotKey [{0}] For \\\"{1}\\\" Error: {2}\",\n                            hotkeyStr,\n                            func,\n                            ex.Message ) );\n                    }\n                }\n            }\n\n            var keyboardHookProc = new User32.HookProc( KeyboardHookCallback );\n            Logger.Info( \"Set Windows LowLevelKeyboardProc Hook\" );\n            LLKH.SetHook( keyboardHookProc );\n\n            if ( Manager.CurrentProfile.Mouse.UseWheelSwitchDesktopWhenOnTaskbar )\n            {\n                EnableMouseHook();\n            }\n        }\n\n        private void EnableMouseHook()\n        {\n            Logger.Info( \"Set Windows LowLevelMouseProc Hook\" );\n            LowLevelMouseHook.SetHook( MouseHookCallback );\n        }\n\n        private static void DisableMouseHook()\n        {\n            Logger.Info( \"Unset Windows LowLevelMouseProc Hook\" );\n            LowLevelMouseHook.UnHook();\n        }\n\n        private IntPtr KeyboardHookCallback( int nCode, IntPtr wParam, IntPtr lParam )\n        {\n            if ( nCode >= 0 )\n            {\n                var info = (LLKH.KBDLLHOOKSTRUCT)Marshal.PtrToStructure( lParam, typeof( LLKH.KBDLLHOOKSTRUCT ) );\n\n                var keyType = (int)wParam;\n\n                if ( IsShowing() && \n                     Manager.Configs.Cluster.EnableWindowFilter &&\n                     info.vkCode == (int)Keys.LShiftKey )\n                {\n                    switch ( keyType )\n                    {\n                        case LLKH.WM_KEYUP:\n                            DoublePressTimer.Restart();\n                            break;\n                        case LLKH.WM_KEYDOWN:\n                        {\n                            if ( DoublePressTimer.ElapsedMilliseconds < Manager.Configs.Cluster.ToggleWindowFilterDoublePressMaxInterval )\n                            {\n                                User32.PostMessage( Handle, WinMsg.WM_HOTKEY, UserMessage.ToggleWindowFilter, 0 );\n                                return LowLevelHooks.Handled;\n                            }\n\n                            break;\n                        }\n                    }\n                }\n\n                if ( keyType != LLKH.WM_KEYDOWN ) goto NEXT;\n\n                /////////////////////////////////////////////////////////////////////////////////\n                // hook [LWin+Tab] to replace TaskView \n                if ( info.vkCode == (int)Keys.Tab\n                     && LLKH.IsKeyHold( Keys.LWin )\n                     && !( LLKH.IsKeyHold( Keys.ControlKey ) || LLKH.IsKeyHold( Keys.ShiftKey ) ) )\n                {\n                    if ( ( info.flags & LLKH.KBDLLHOOKSTRUCTFlags.LLKHF_INJECTED ) == 0 ) // not come from fake input\n                    {\n                        LLKH.MultipleKeyPress( new List<Keys> {(Keys)LLKH.DUMMY_KEY} );\n                        User32.PostMessage( Handle, WinMsg.WM_HOTKEY, UserMessage.RiseView, 0 );\n                        return LowLevelHooks.Handled;\n                    }\n\n                    goto NEXT;\n                }\n\n                /////////////////////////////////////////////////////////////////////////////////\n                // since we hook default [LWin+Tab],\n                // we should use a alternative way to rise the TaskView in case user want it.\n                // here choose [Ctrl+LWin+Shift+Tab] to try to avoid conflicts\n                if ( info.vkCode == (int)Keys.Tab\n                     && LLKH.IsKeyHold( Keys.LWin )\n                     && LLKH.IsKeyHold( Keys.ControlKey )\n                     && LLKH.IsKeyHold( Keys.ShiftKey ) )\n                {\n                    if ( ( info.flags & LLKH.KBDLLHOOKSTRUCTFlags.LLKHF_INJECTED ) == 0 // not come from fake input\n                         && RiseTaskViewTimer.ElapsedMilliseconds > Const.RiseViewInterval )\n                    {\n                        LLKH.MultipleKeyPress( new List<Keys> {(Keys)LLKH.DUMMY_KEY} );\n                        LLKH.MultipleKeyUp( new List<Keys> {Keys.ControlKey, Keys.LWin, Keys.ShiftKey, Keys.Tab} );\n                        LLKH.MultipleKeyPress( new List<Keys> {Keys.LWin, Keys.Tab} );\n                        LLKH.MultipleKeyDown( new List<Keys> {Keys.ControlKey, Keys.LWin, Keys.ShiftKey} );\n                        RiseTaskViewTimer.Restart();\n                    }\n\n                    return LowLevelHooks.Handled;\n                }\n\n                /////////////////////////////////////////////////////////////////////////////////\n                // hook [LWin+LCtrl+<DirKey>] for switch virtual desktop\n                if ( LLKH.IsKeyHold( Keys.LWin )\n                     && LLKH.IsKeyHold( Keys.LControlKey )\n                     && !( LLKH.IsKeyHold( Keys.ShiftKey ) || LLKH.IsKeyHold( Keys.Menu ) ) )\n                {\n                    var key = (Keys)info.vkCode;\n                    switch ( key )\n                    {\n                        case Keys.Left:\n                        case Keys.Right:\n                        case Keys.Up:\n                        case Keys.Down:\n                            User32.PostMessage( Handle, WinMsg.WM_HOTKEY, UserMessage.SwitchDesktop, (ulong)key );\n                            return LowLevelHooks.Handled;\n                    }\n\n                    goto NEXT;\n                }\n\n                /////////////////////////////////////////////////////////////////////////////////\n                // hook [Esc] to hide MainView\n                if ( info.vkCode == (int)Keys.Escape && IsShowing() )\n                {\n                    HideAll();\n                    return LowLevelHooks.Handled;\n                }\n            }\n\n            NEXT:\n            return User32.CallNextHookEx( LLKH.HookId, nCode, wParam, lParam );\n        }\n\n        private IntPtr MouseHookCallback( int nCode, IntPtr wParam, IntPtr lParam )\n        {\n            if ( nCode < 0 ) goto NEXT;\n\n            var hTaskbar = User32.FindWindow( Const.TaskbarWndClass, \"\" );\n            if ( hTaskbar == IntPtr.Zero ) goto NEXT;\n\n            var info = (LowLevelMouseHook.MSLLHOOKSTRUCT)Marshal.PtrToStructure( lParam, typeof( LowLevelMouseHook.MSLLHOOKSTRUCT ) );\n            var msg  = (int)wParam;\n            if ( msg == LowLevelMouseHook.WM_MOUSEWHEEL )\n            {\n                var zOrder = WindowTool.GetZOrderByHandle( hTaskbar );\n                if ( zOrder > Manager.CurrentProfile.Mouse.TaskbarVisibilityThreshold ) goto NEXT;\n\n                var rect = new RECT();\n                _ = User32.GetWindowRect( hTaskbar, ref rect );\n                if ( info.pt.X >= rect.Left && info.pt.Y > rect.Top )\n                {\n                    uint dir;\n                    if ( LLKH.IsKeyHold( Keys.ShiftKey ) )\n                    {\n                        dir = (uint)( info.mouseData >> 16 > 0 ? Keys.Up : Keys.Down );\n                    }\n                    else\n                    {\n                        dir = (uint)( info.mouseData >> 16 > 0 ? Keys.Left : Keys.Right );\n                    }\n\n                    User32.PostMessage( Handle, WinMsg.WM_HOTKEY, UserMessage.SwitchDesktop, dir );\n                    return LowLevelHooks.Handled;\n                }\n            }\n\n            NEXT:\n            return User32.CallNextHookEx( LowLevelMouseHook.HookId, nCode, wParam, lParam );\n        }\n\n        private void Window_Closing( object sender, CancelEventArgs e )\n        {\n            Logger.Info( \"Unset Windows LowLevelKeyboardProc Hook\" );\n            LLKH.UnHook();\n\n            DisableMouseHook();\n\n            Logger.Info( \"Unregister Global HotKeys\" );\n            GHK.UnRegAllHotKey();\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/MainWindow.layout.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Windows;\nusing System.Windows.Controls;\nusing System.Windows.Media;\nusing System.Windows.Media.Effects;\nusing System.Windows.Threading;\nusing VirtualSpace.Config;\nusing VirtualSpace.Config.Entity;\nusing VirtualSpace.Helpers;\nusing VirtualSpace.VirtualDesktop;\nusing VirtualSpace.VirtualDesktop.Api;\n\nnamespace VirtualSpace\n{\n    public partial class MainWindow\n    {\n        private static int              _desktopCount;\n        private static UserInterface    Ui       => Manager.CurrentProfile.UI;\n        private static int              RowsCols { get; set; }\n        private static DropShadowEffect _borderShadowDefault;\n        private static DropShadowEffect _borderShadowCurrent;\n\n        public static void ResetMainGrid()\n        {\n            var vdCount = DesktopWrapper.Count;\n            if ( vdCount == _desktopCount ) return;\n            var rowsCols = (int)Math.Ceiling( Math.Sqrt( vdCount ) );\n\n            var mainGrid = _instance.MainGrid;\n\n            mainGrid.Children.Clear();\n            mainGrid.RowDefinitions.Clear();\n            mainGrid.ColumnDefinitions.Clear();\n\n            if ( RowsCols != rowsCols )\n            {\n                _instance.Dispatcher.Invoke( new Action( () => { } ), DispatcherPriority.ContextIdle, null );\n            }\n\n            var borderBrushDefault = new SolidColorBrush\n                {Color = Color.FromRgb( Ui.VDWDefaultBackColor.R, Ui.VDWDefaultBackColor.G, Ui.VDWDefaultBackColor.B )};\n\n            for ( var r = 0; r < rowsCols; r++ )\n            {\n                mainGrid.RowDefinitions.Add( new RowDefinition() );\n                mainGrid.ColumnDefinitions.Add( new ColumnDefinition() );\n                for ( var c = 0; c < rowsCols; c++ )\n                {\n                    var border = new Border\n                    {\n                        Margin = new Thickness( Ui.VDWMargin ),\n                        BorderThickness = new Thickness( Ui.VDWBorderSize ),\n                        BorderBrush = borderBrushDefault,\n                        Effect = _borderShadowDefault,\n                        Background = Brushes.Transparent\n                    };\n                    Grid.SetRow( border, r );\n                    Grid.SetColumn( border, c );\n                    mainGrid.Children.Add( border );\n                }\n            }\n\n            _desktopCount = vdCount; // remember last count\n            RowsCols = rowsCols;\n            _instance.UpdateLayout();\n        }\n\n        public static void ResetMainGridForSingleDesktop( int vdIndex )\n        {\n            var vdCount  = DesktopWrapper.Count;\n            var rowsCols = (int)Math.Ceiling( Math.Sqrt( vdCount ) );\n\n            vdIndex = VirtualDesktopManager.GetMatrixIndexByVdIndex( vdIndex );\n\n            var bigRow          = vdIndex / rowsCols;\n            var bigCol          = vdIndex % rowsCols;\n            var bigGridLength   = new GridLength( 1, GridUnitType.Star );\n            var smallGridLength = new GridLength( 0 );\n\n            var mainGrid = _instance.MainGrid;\n\n            mainGrid.Children.Clear();\n            mainGrid.RowDefinitions.Clear();\n            mainGrid.ColumnDefinitions.Clear();\n\n            _instance.Dispatcher.Invoke( new Action( () => { } ), DispatcherPriority.ContextIdle, null );\n\n            var borderBrushDefault = new SolidColorBrush\n                {Color = Color.FromRgb( Ui.VDWDefaultBackColor.R, Ui.VDWDefaultBackColor.G, Ui.VDWDefaultBackColor.B )};\n\n            for ( var r = 0; r < rowsCols; r++ )\n            {\n                var height = bigRow == r ? bigGridLength : smallGridLength;\n                mainGrid.RowDefinitions.Add( new RowDefinition {Height = height} );\n\n                for ( var c = 0; c < rowsCols; c++ )\n                {\n                    if ( mainGrid.ColumnDefinitions.Count < rowsCols )\n                    {\n                        var width = bigCol == c ? bigGridLength : smallGridLength;\n                        mainGrid.ColumnDefinitions.Add( new ColumnDefinition {Width = width} );\n                    }\n\n                    var border = mainGrid.ColumnDefinitions[c].Width == smallGridLength\n                        ? new Border()\n                        : new Border\n                        {\n                            Margin = new Thickness( Ui.VDWMargin ),\n                            BorderThickness = new Thickness( Ui.VDWBorderSize ),\n                            BorderBrush = borderBrushDefault,\n                            Effect = _borderShadowDefault,\n                            Background = Brushes.Transparent\n                        };\n                    Grid.SetRow( border, r );\n                    Grid.SetColumn( border, c );\n                    mainGrid.Children.Add( border );\n                }\n            }\n\n            _desktopCount = 1; // single, single, single\n            RowsCols = rowsCols;\n            _instance.UpdateLayout();\n        }\n\n        public static void UpdateHoverBorder( int hover )\n        {\n            var borderColorHover = new SolidColorBrush\n                {Color = Color.FromRgb( Ui.VDWHighlightBackColor.R, Ui.VDWHighlightBackColor.G, Ui.VDWHighlightBackColor.B )};\n            var borderColorDefault = new SolidColorBrush\n                {Color = Color.FromRgb( Ui.VDWDefaultBackColor.R, Ui.VDWDefaultBackColor.G, Ui.VDWDefaultBackColor.B )};\n\n            for ( var i = 0; i < _desktopCount; i++ )\n            {\n                var border = (Border)_instance.MainGrid.Children[i];\n                border.BorderBrush = i == hover ? borderColorHover : borderColorDefault;\n            }\n        }\n\n        public static void RenderCellBorder()\n        {\n            var currentMatrixIndex = VirtualDesktopManager.GetMatrixIndexByVdIndex( VirtualDesktopManager.GetVdIndexByGuid( DesktopWrapper.CurrentGuid ) );\n\n            var borderColorHover = Color.FromRgb( Ui.VDWHighlightBackColor.R, Ui.VDWHighlightBackColor.G, Ui.VDWHighlightBackColor.B );\n\n            var borderBrushDefault = new SolidColorBrush\n                {Color = Color.FromRgb( Ui.VDWDefaultBackColor.R, Ui.VDWDefaultBackColor.G, Ui.VDWDefaultBackColor.B )};\n            var borderBrushCurrent = new SolidColorBrush\n                {Color = Color.FromRgb( Ui.VDWCurrentBackColor.R, Ui.VDWCurrentBackColor.G, Ui.VDWCurrentBackColor.B )};\n\n            for ( var i = 0; i < Math.Pow( RowsCols, 2 ); i++ )\n            {\n                var border = (Border)_instance.MainGrid.Children[i];\n                if ( i == currentMatrixIndex )\n                {\n                    border.Effect = _borderShadowCurrent;\n                    border.BorderBrush = borderBrushCurrent;\n                }\n                else\n                {\n                    var effect = border.Effect as DropShadowEffect;\n                    var brush  = border.BorderBrush as SolidColorBrush;\n                    if ( effect?.Color == Colors.White\n                         || brush?.Color == borderColorHover )\n                    {\n                        border.Effect = _borderShadowDefault;\n                        border.BorderBrush = borderBrushDefault;\n                    }\n                }\n            }\n        }\n\n        public static Point GetCellLocationByMatrixIndex( int index )\n        {\n            if ( _instance.Dispatcher.CheckAccess() )\n            {\n                return _instance.MainGrid.Children[index].TranslatePoint( new Point(), _instance );\n            }\n\n            return _instance.Dispatcher.Invoke( () => _instance.MainGrid.Children[index].TranslatePoint( new Point(), _instance ) );\n        }\n\n        public static Size GetCellSizeByMatrixIndex( int index )\n        {\n            return _instance.MainGrid.Children[index].RenderSize;\n        }\n\n        public static int InCell( Point p )\n        {\n            var cells = _instance.MainGrid.Children;\n            var index = -1;\n            var dpi   = SysInfo.Dpi;\n            for ( var i = 0; i < cells.Count; i++ )\n            {\n                var topLeft = cells[i].TranslatePoint( new Point(), _instance );\n                topLeft = new Point( topLeft.X * dpi.ScaleX, topLeft.Y * dpi.ScaleY );\n                var bottomRight = new Point( topLeft.X + cells[i].RenderSize.Width * dpi.ScaleX, topLeft.Y + cells[i].RenderSize.Height * dpi.ScaleY );\n                var rect        = new Rect( topLeft, bottomRight );\n                if ( rect.Contains( p ) )\n                {\n                    index = i;\n                    break;\n                }\n            }\n\n            return index;\n        }\n\n        private void InitCellBorderShadowEffect()\n        {\n            _borderShadowDefault = Resources[\"VdwShadowDefault\"] as DropShadowEffect;\n            _borderShadowCurrent = Resources[\"VdwShadowCurrent\"] as DropShadowEffect;\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/MainWindow.main.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Diagnostics;\nusing System.Windows;\nusing System.Windows.Interop;\nusing System.Windows.Media;\nusing VirtualSpace.Config;\nusing VirtualSpace.Factory;\nusing VirtualSpace.Helpers;\nusing VirtualSpace.Tools;\nusing VirtualSpace.VirtualDesktop;\nusing VirtualSpace.VirtualDesktop.Api;\nusing ConfigManager = VirtualSpace.Config.Manager;\n\nnamespace VirtualSpace\n{\n    public partial class MainWindow\n    {\n        private static readonly Stopwatch      RiseViewTimer      = Stopwatch.StartNew();\n        private static readonly Stopwatch      SwitchDesktopTimer = Stopwatch.StartNew();\n        private static          MainWindow     _instance;\n        private static          long           _forceSwitchOnTimeout;\n        private                 IAppController _acForm;\n\n        public static IAppController AcForm\n        {\n            get\n            {\n                if ( _instance._acForm is null )\n                {\n                    _instance._acForm = AppControllerFactory.Create();\n                    _instance._acForm.SetMainWindowHandle( _instance.Handle );\n                }\n\n                return _instance._acForm;\n            }\n            private set => _instance._acForm = value;\n        }\n\n        private MainWindow()\n        {\n            InitializeComponent();\n            DataContext = this;\n            _instance = this;\n\n            Left = 0;\n            Top = 0;\n            Width = SystemParameters.PrimaryScreenWidth;\n            Height = SystemParameters.PrimaryScreenHeight;\n            Topmost = true;\n            Title = Const.Window.VD_FRAME_TITLE;\n        }\n\n        public IntPtr Handle { get; private set; }\n\n        public static MainWindow GetMainWindow()\n        {\n            return _instance;\n        }\n\n        public static MainWindow Create( IAppController ac )\n        {\n            var mw = new MainWindow\n            {\n                _acForm = ac,\n                Background = new SolidColorBrush(\n                    Color.FromArgb(\n                        Ui.CanvasOpacity,\n                        Ui.CanvasBackColor.R,\n                        Ui.CanvasBackColor.G,\n                        Ui.CanvasBackColor.B )\n                ),\n                BlurOpacity = Ui.CanvasOpacity,\n                BlurBackgroundColor = Ui.CanvasBackColor.GetLongOfColor()\n            };\n\n            new WindowInteropHelper( mw ).EnsureHandle();\n\n            mw.InitCellBorderShadowEffect();\n\n            return mw;\n        }\n\n        public static void NotifyDesktopManagerReset()\n        {\n            User32.SendMessage( _instance.Handle, (int)_instance._taskbarCreatedMessage, 0, 0 );\n        }\n\n        protected override void OnSourceInitialized( EventArgs e )\n        {\n            base.OnSourceInitialized( e );\n            Handle = new WindowInteropHelper( this ).EnsureHandle();\n            var source = HwndSource.FromHwnd( Handle );\n            source?.AddHook( WndProc );\n\n            Bootstrap();\n        }\n\n        private async void Window_Loaded( object sender, RoutedEventArgs e )\n        {\n            VirtualDesktopManager.Bootstrap();\n            await VirtualDesktopManager.InitLayout();\n\n            UpdateVDIndexOnTrayIcon( DesktopWrapper.CurrentGuid );\n\n            DesktopManagerWrapper.ListenVirtualDesktopEvents();\n            VirtualDesktopManager.RegisterVirtualDesktopEvents();\n\n            if ( ConfigManager.Configs.Cluster.HideOnStart ||\n                 ( (App)Application.Current ).HideOnStart ) return;\n\n            VirtualDesktopManager.ShowAllVirtualDesktops();\n            VirtualDesktopManager.ShowVisibleWindowsForDesktops();\n        }\n\n        private void Bootstrap()\n        {\n            AcForm.SetMainWindowHandle( Handle );\n            RegisterHotKey( Handle );\n            FixStyle();\n            EnableBlur();\n            RegisterSystemMessages();\n        }\n\n        public void FakeHide()\n        {\n            Hide();\n        }\n\n        private static void BringToTop( int processId = 0 )\n        {\n            TopShow();\n\n            VirtualDesktopManager.FixLayout();\n            VirtualDesktopManager.ShowAllVirtualDesktops();\n\n            if ( processId > 0 )\n            {\n                VirtualDesktopManager.ShowVisibleWindowsForDesktops( null, processId );\n            }\n            else\n            {\n                VirtualDesktopManager.ShowVisibleWindowsForDesktops();\n            }\n\n            if ( _instance.Canvas.RowDefinitions[1].Height.Value > 0 )\n                _instance.ShowFilterWindow();\n        }\n\n        private static void BringToTopForCurrentVd( int processId = 0 )\n        {\n            TopShow();\n\n            var cvd = VirtualDesktopManager.GetCurrentVdw();\n            cvd.MakeTheOnlyOne( processId );\n        }\n\n        private static void TopShow()\n        {\n            CheckScreenArea();\n\n            _instance.Left = 0;\n            _instance.Top = 0;\n            _instance.Show();\n        }\n\n        private static void CheckScreenArea()\n        {\n            if ( (int)_instance.Width == (int)SystemParameters.PrimaryScreenWidth &&\n                 (int)_instance.Height == (int)SystemParameters.PrimaryScreenHeight ) return;\n            _instance.Width = SystemParameters.PrimaryScreenWidth;\n            _instance.Height = SystemParameters.PrimaryScreenHeight;\n        }\n\n        public static void HideAll()\n        {\n            _instance.Hide();\n            HideFilterWindow();\n            VirtualDesktopManager.HideAllVirtualDesktops();\n        }\n\n        public static bool IsShowing()\n        {\n            return _instance.IsVisible;\n        }\n\n        public static void UpdateVDIndexOnTrayIcon( Guid guid )\n        {\n            if ( !Manager.Configs.Cluster.ShowVDIndexOnTrayIcon )\n            {\n                TrayIcon.InitTrayIcon();\n                return;\n            }\n\n            var i     = ConfigManager.CurrentProfile.DesktopOrder.IndexOf( guid );\n            var index = ConfigManager.CurrentProfile.UI.ShowVdIndexType == 0 ? i : i + 1;\n            TrayIcon.UpdateVDIndexOnTrayIcon( index.ToString() );\n        }\n\n        private static void TryRunAsAdmin()\n        {\n            RestartApp( true );\n        }\n\n        private static void RestartApp( bool runas = false )\n        {\n            var app = (App)Application.Current;\n            var psi = new ProcessStartInfo\n            {\n                FileName = ConfigManager.AppPath,\n                UseShellExecute = true\n            };\n\n            if ( runas ) psi.Verb = \"runas\";\n\n            try\n            {\n                app.ReleaseMutex();\n                Process.Start( psi );\n                Application.Current.Shutdown();\n            }\n            catch\n            {\n                App.TryMutex();\n            }\n        }\n\n        public static void Quit()\n        {\n            _instance.Close();\n            Application.Current.Shutdown();\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/MainWindow.message.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Linq;\nusing System.Runtime.InteropServices;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing System.Windows.Forms;\nusing System.Windows.Input;\nusing VirtualSpace.AppLogs;\nusing VirtualSpace.Commons;\nusing VirtualSpace.Config;\nusing VirtualSpace.Factory;\nusing VirtualSpace.Helpers;\nusing VirtualSpace.Plugin;\nusing VirtualSpace.Tools;\nusing VirtualSpace.VirtualDesktop;\nusing VirtualSpace.VirtualDesktop.Api;\n\nnamespace VirtualSpace\n{\n    public partial class MainWindow\n    {\n        private uint _taskbarCreatedMessage;\n\n        private void RegisterSystemMessages()\n        {\n            _taskbarCreatedMessage = User32.RegisterWindowMessage( Const.TaskbarCreated );\n            foreach ( var strMsg in PluginHost.CareAboutMessages.Keys )\n            {\n                PluginHost.CareAboutMessages[strMsg] = User32.RegisterWindowMessage( strMsg );\n            }\n        }\n\n        private void Window_MouseDown( object sender, MouseButtonEventArgs e )\n        {\n            var profile = Manager.CurrentProfile;\n            if ( e.ChangedButton == MouseButton.Left )\n            {\n                switch ( profile.Mouse.LeftClickOnCanvas )\n                {\n                    case 0:\n                        break;\n                    case 1:\n                        HideAll();\n                        break;\n                    default:\n                        HideAll();\n                        break;\n                }\n            }\n            else if ( e.ChangedButton == MouseButton.Right )\n            {\n                switch ( profile.Mouse.RightClickOnCanvas )\n                {\n                    case 0:\n                        break;\n                    case 1:\n                        HideAll();\n                        break;\n                    default:\n                        HideAll();\n                        break;\n                }\n            }\n            else if ( e.ChangedButton == MouseButton.Middle )\n            {\n                switch ( profile.Mouse.MiddleClickOnCanvas )\n                {\n                    case 0:\n                        break;\n                    case 1:\n                        HideAll();\n                        break;\n                    default:\n                        HideAll();\n                        break;\n                }\n            }\n        }\n\n        private IntPtr WndProc( IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled )\n        {\n            if ( msg == _taskbarCreatedMessage )\n            {\n                Logger.Warning( \"explorer.exe restarted, reset DesktopManager and restart all Plugins.\" );\n\n                DesktopManagerWrapper.ResetDesktopManager();\n\n                foreach ( var plugin in PluginHost.Plugins )\n                {\n                    PluginHost.RestartPlugin( plugin );\n                }\n\n                goto RETURN;\n            }\n\n            if ( PluginHost.CareAboutMessages.ContainsValue( (uint)msg ) )\n            {\n                var (key, _) = PluginHost.CareAboutMessages.First( m => m.Value == msg );\n                foreach ( var plugin in PluginHost.Plugins.Where( plugin =>\n                             plugin.RestartPolicy?.Trigger == PolicyTrigger.WINDOWS_MESSAGE &&\n                             plugin.RestartPolicy.Enabled &&\n                             plugin.RestartPolicy.Values.Contains( key ) ) )\n                {\n                    Logger.Info( $\"Restart Plugin {plugin.Display} because {key}\" );\n                    PluginHost.RestartPlugin( plugin );\n                }\n\n                foreach ( var plugin in PluginHost.Plugins.Where( plugin =>\n                             plugin.ClosePolicy?.Trigger == PolicyTrigger.WINDOWS_MESSAGE &&\n                             plugin.ClosePolicy.Enabled &&\n                             plugin.ClosePolicy.Values.Contains( key ) ) )\n                {\n                    Logger.Info( $\"Close Plugin {plugin.Display} because {key}\" );\n                    PluginHost.ClosePlugin( plugin );\n                }\n\n                goto RETURN;\n            }\n\n            void SwitchByIndex( int index )\n            {\n                if ( Manager.CurrentProfile.DesktopOrder.Count > index )\n                    DesktopWrapper.MakeVisibleByGuid( Manager.CurrentProfile.DesktopOrder[index] );\n            }\n\n            void MoveForegroundWindowToDesktop( int sysIndex, bool follow = false )\n            {\n                if ( sysIndex >= DesktopWrapper.Count ) return;\n\n                var fw = User32.GetForegroundWindow();\n                if ( fw == IntPtr.Zero ) return;\n\n                try\n                {\n                    DesktopWrapper.MoveWindowToDesktop( fw, sysIndex );\n\n                    if ( !follow ) return;\n\n                    WindowTool.ActiveWindow( fw, sysIndex );\n                }\n                catch ( Exception ex )\n                {\n                    Logger.Error( $\"Move Foreground Window To Desktop[{sysIndex}] ∵ \" + ex.Message );\n                }\n            }\n\n            switch ( msg )\n            {\n                case WinMsg.WM_SYSCOMMAND:\n                    var wP = wParam.ToInt32();\n                    if ( wP is WinMsg.SC_RESTORE or WinMsg.SC_MINIMIZE or WinMsg.SC_MAXIMIZE )\n                        handled = true;\n                    break;\n                case WinMsg.WM_HOTKEY:\n\n                    var um = wParam.ToInt32();\n                    switch ( um )\n                    {\n                        case > UserMessage.Meta.SVD_START and <= UserMessage.Meta.SVD_END:\n                            SwitchByIndex( um % UserMessage.Meta.SVD_START - 1 );\n                            break;\n                        case > UserMessage.Meta.MW_START and <= UserMessage.Meta.MW_END:\n                            MoveForegroundWindowToDesktop( um % UserMessage.Meta.MW_START - 1 );\n                            break;\n                        case > UserMessage.Meta.MWF_START and <= UserMessage.Meta.MWF_END:\n                            MoveForegroundWindowToDesktop( um % UserMessage.Meta.MWF_START - 1, true );\n                            break;\n                        case UserMessage.RiseView:\n                            if ( Manager.Configs.Cluster.HideMainViewIfItsShown && IsShowing() )\n                            {\n                                HideAll();\n                            }\n                            else if ( RiseViewTimer.ElapsedMilliseconds > Const.RiseViewInterval )\n                            {\n                                BringToTop();\n                                RiseViewTimer.Restart();\n                            }\n\n                            break;\n                        case UserMessage.RiseViewForActiveApp:\n                            _ = User32.GetWindowThreadProcessId( User32.GetForegroundWindow(), out var processId );\n                            if ( Manager.Configs.Cluster.HideMainViewIfItsShown && IsShowing() )\n                            {\n                                HideAll();\n                            }\n                            else if ( RiseViewTimer.ElapsedMilliseconds > Const.RiseViewInterval )\n                            {\n                                BringToTop( processId );\n                                RiseViewTimer.Restart();\n                            }\n\n                            break;\n                        case UserMessage.RiseViewForCurrentVD:\n                            if ( Manager.Configs.Cluster.HideMainViewIfItsShown && IsShowing() )\n                            {\n                                HideAll();\n                            }\n                            else if ( RiseViewTimer.ElapsedMilliseconds > Const.RiseViewInterval )\n                            {\n                                BringToTopForCurrentVd();\n                                RiseViewTimer.Restart();\n                            }\n\n                            break;\n                        case UserMessage.RiseViewForActiveAppInCurrentVD:\n                            _ = User32.GetWindowThreadProcessId( User32.GetForegroundWindow(), out var pId );\n                            if ( Manager.Configs.Cluster.HideMainViewIfItsShown && IsShowing() )\n                            {\n                                HideAll();\n                            }\n                            else if ( RiseViewTimer.ElapsedMilliseconds > Const.RiseViewInterval )\n                            {\n                                BringToTopForCurrentVd( pId );\n                                RiseViewTimer.Restart();\n                            }\n\n                            break;\n                        case UserMessage.ShowAppController:\n                            AcForm.BringToTop();\n                            break;\n                        case UserMessage.ToggleWindowFilter:\n                            ToggleWindowFilter();\n                            break;\n                        case UserMessage.RestartAppController:\n                            AcForm.Quit();\n                            AcForm = AppControllerFactory.Create();\n                            AcForm.SetMainWindowHandle( Handle );\n                            AcForm.BringToTop();\n\n                            UpdateVDIndexOnTrayIcon( DesktopWrapper.CurrentGuid );\n                            break;\n                        case UserMessage.AppControllerClosed:\n                            AcForm = null;\n                            break;\n                        case UserMessage.SwitchDesktop:\n                            SwitchDesktopByDirection( lParam );\n                            break;\n                        case UserMessage.SwitchBackToLastDesktop:\n                            SwitchToDesktopById( VirtualDesktopManager.LastDesktopId );\n                            break;\n                        case UserMessage.DesktopArrangement:\n                            if ( IsShowing() )\n                            {\n                                VirtualDesktopManager.ShowAllVirtualDesktops();\n                            }\n\n                            break;\n                        case UserMessage.RefreshTrayIcon:\n                            UpdateVDIndexOnTrayIcon( DesktopWrapper.CurrentGuid );\n                            break;\n                        case UserMessage.UpdateTrayLang:\n                            TrayIcon.SetLang();\n                            break;\n                        case UserMessage.RunAsAdministrator:\n                            TryRunAsAdmin();\n                            goto RETURN;\n                        case UserMessage.RestartApp:\n                            RestartApp();\n                            goto RETURN;\n                        case UserMessage.EnableMouseHook:\n                            EnableMouseHook();\n                            goto RETURN;\n                        case UserMessage.DisableMouseHook:\n                            DisableMouseHook();\n                            goto RETURN;\n                        case UserMessage.NavLeft:\n                            SwitchDesktopByDirection( (IntPtr)Keys.Left );\n                            break;\n                        case UserMessage.NavRight:\n                            SwitchDesktopByDirection( (IntPtr)Keys.Right );\n                            break;\n                        case UserMessage.NavUp:\n                            SwitchDesktopByDirection( (IntPtr)Keys.Up );\n                            break;\n                        case UserMessage.NavDown:\n                            SwitchDesktopByDirection( (IntPtr)Keys.Down );\n                            break;\n                    }\n\n                    break;\n                case WinApi.UM_SWITCHDESKTOP:\n                    var targetMatrixIndex = wParam.ToInt32();\n                    if ( targetMatrixIndex >= 0 && targetMatrixIndex < DesktopWrapper.Count )\n                    {\n                        Interlocked.Exchange( ref _forceSwitchOnTimeout, 0 );\n                        DesktopWrapper.MakeVisibleByGuid(\n                            Manager.CurrentProfile.DesktopOrder[VirtualDesktopManager.GetVdIndexByMatrixIndex( targetMatrixIndex )] );\n                    }\n\n                    break;\n                // case WinMsg.WM_MOUSEACTIVATE:\n                //     handled = true;\n                //     return new IntPtr( WinMsg.MA_NOACTIVATE );\n            }\n\n            RETURN:\n            return IntPtr.Zero;\n        }\n\n        private static void SwitchToDesktopById( Guid guid )\n        {\n            if ( guid == Guid.Empty ) return;\n            if ( SwitchDesktopTimer.ElapsedMilliseconds <= Const.SwitchDesktopInterval ) return;\n\n            DesktopWrapper.MakeVisibleByGuid( guid );\n            SwitchDesktopTimer.Restart();\n        }\n\n        private void SwitchDesktopByDirection( IntPtr lParam )\n        {\n            if ( SwitchDesktopTimer.ElapsedMilliseconds <= Const.SwitchDesktopInterval ) return;\n\n            var desktopOrder              = Manager.CurrentProfile.DesktopOrder;\n            var currentVdIndex            = desktopOrder.IndexOf( DesktopWrapper.CurrentGuid );\n            var currentDesktopMatrixIndex = VirtualDesktopManager.GetMatrixIndexByVdIndex( currentVdIndex );\n\n            var dir = lParam.ToInt32();\n            var targetMatrixIndex = Navigation.CalculateTargetIndex(\n                DesktopWrapper.Count,\n                currentVdIndex,\n                (Keys)dir,\n                Manager.CurrentProfile.Navigation );\n\n            var vDsi = new VirtualDesktopSwitchInfo\n            {\n                hostHandle = Handle,\n                vdCount = DesktopWrapper.Count,\n                fromIndex = currentDesktopMatrixIndex,\n                dir = dir,\n                targetIndex = targetMatrixIndex\n            };\n            var vDsiSize = Marshal.SizeOf( typeof( VirtualDesktopSwitchInfo ) );\n            var pVDsi    = Marshal.AllocHGlobal( vDsiSize );\n            Marshal.StructureToPtr( vDsi, pVDsi, true );\n\n            var cds = new COPYDATASTRUCT\n            {\n                dwData = (IntPtr)WinApi.UM_SWITCHDESKTOP,\n                cbData = vDsiSize,\n                lpData = pVDsi\n            };\n            var pCds = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( COPYDATASTRUCT ) ) );\n            Marshal.StructureToPtr( cds, pCds, true );\n\n            foreach ( var pluginInfo in PluginHost.Plugins.Where(\n                         p => p.Type == PluginType.VD_SWITCH_OBSERVER && User32.IsWindow( p.Handle ) ) )\n            {\n                User32.SendMessage( pluginInfo.Handle, WinApi.WM_COPYDATA, 0, (ulong)pCds );\n            }\n\n            ////////////////////////////////////////////////////////////////////////////////////\n            // if none of plugins send back message after 100 ms, host will force switch desktop\n            Interlocked.Increment( ref _forceSwitchOnTimeout );\n            Task.Run( () =>\n            {\n                Thread.Sleep( 100 );\n                if ( _forceSwitchOnTimeout == 0 ) return;\n                DesktopWrapper.MakeVisibleByGuid( desktopOrder[VirtualDesktopManager.GetVdIndexByMatrixIndex( targetMatrixIndex )] );\n            } );\n\n            Marshal.FreeHGlobal( pVDsi );\n            Marshal.FreeHGlobal( pCds );\n            SwitchDesktopTimer.Restart();\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/MainWindow.style.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System.Runtime.InteropServices;\nusing VirtualSpace.Helpers;\n\nnamespace VirtualSpace\n{\n    public partial class MainWindow\n    {\n        private uint _blurOpacity;\n        private uint BlurBackgroundColor { get; set; } = 0x555555;\n\n        private uint BlurOpacity\n        {\n            get => _blurOpacity;\n            set\n            {\n                _blurOpacity = value;\n                EnableBlur();\n            }\n        }\n\n        private void FixStyle()\n        {\n            var style = User32.GetWindowLong( Handle, (int)GetWindowLongFields.GWL_STYLE );\n            style = unchecked(style | (int)0x80000000); // WS_POPUP\n            User32.SetWindowLongPtr( new HandleRef( this, Handle ), (int)GetWindowLongFields.GWL_STYLE, style );\n\n            var exStyle = User32.GetWindowLong( Handle, (int)GetWindowLongFields.GWL_EXSTYLE );\n            exStyle |= 0x08000000; // WS_EX_NOACTIVATE\n            exStyle &= ~0x00040000; // WS_EX_APPWINDOW\n            User32.SetWindowLongPtr( new HandleRef( this, Handle ), (int)GetWindowLongFields.GWL_EXSTYLE, exStyle );\n        }\n\n        private void EnableBlur()\n        {\n            var accent = new VisualEffects.AccentPolicy\n            {\n                AccentState = VisualEffects.AccentState.ACCENT_ENABLE_ACRYLICBLURBEHIND,\n                GradientColor = ( BlurOpacity << 24 ) | ( BlurBackgroundColor & 0xFFFFFF )\n            };\n\n            var accentStructSize = Marshal.SizeOf( accent );\n            var accentPtr        = Marshal.AllocHGlobal( accentStructSize );\n            Marshal.StructureToPtr( accent, accentPtr, false );\n\n            var data = new VisualEffects.WindowCompositionAttributeData\n            {\n                Attribute = VisualEffects.WindowCompositionAttribute.WCA_ACCENT_POLICY,\n                SizeOfData = accentStructSize,\n                Data = accentPtr\n            };\n\n            _ = VisualEffects.SetWindowCompositionAttribute( Handle, ref data );\n\n            Marshal.FreeHGlobal( accentPtr );\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/MainWindow.xaml",
    "content": "﻿<Window x:Class=\"VirtualSpace.MainWindow\"\n        xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n        xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n        xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n        xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n        mc:Ignorable=\"d\"\n        BorderThickness=\"0\" Background=\"#01000000\"\n        ResizeMode=\"NoResize\" ShowInTaskbar=\"False\" WindowStyle=\"None\"\n        Left=\"0\" Top=\"0\" Width=\"1280\" Height=\"720\"\n        MouseDown=\"Window_MouseDown\"\n        Loaded=\"Window_Loaded\"\n        Closing=\"Window_Closing\">\n    <Window.Resources>\n        <ResourceDictionary>\n            <DropShadowEffect x:Key=\"VdwShadowDefault\" Opacity=\"1\" ShadowDepth=\"1\" Color=\"Black\" BlurRadius=\"10\"></DropShadowEffect>\n            <DropShadowEffect x:Key=\"VdwShadowCurrent\" Opacity=\"1\" ShadowDepth=\"1\" Color=\"White\" BlurRadius=\"10\"></DropShadowEffect>\n        </ResourceDictionary>\n    </Window.Resources>\n    <WindowChrome.WindowChrome>\n        <WindowChrome GlassFrameThickness=\"-1\" CaptionHeight=\"0\" />\n    </WindowChrome.WindowChrome>\n    <Grid x:Name=\"Canvas\">\n        <Grid.RowDefinitions>\n            <RowDefinition Height=\"*\"></RowDefinition>\n            <RowDefinition Height=\"0\"></RowDefinition>\n        </Grid.RowDefinitions>\n        <Grid x:Name=\"MainGrid\" />\n    </Grid>\n\n</Window>"
  },
  {
    "path": "VirtualSpace/MainWindow.xaml.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System.Windows;\n\nnamespace VirtualSpace\n{\n    /// <summary>\n    ///     Interaction logic for MainWindow.xaml\n    /// </summary>\n    public partial class MainWindow : Window\n    {\n    }\n}"
  },
  {
    "path": "VirtualSpace/Program.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.IO;\nusing System.Reflection;\nusing System.Windows;\nusing VirtualSpace.AppLogs;\nusing VirtualSpace.Config;\nusing VirtualSpace.Helpers;\n\nnamespace VirtualSpace\n{\n    public static class Program\n    {\n        [STAThread]\n        public static void Main()\n        {\n            LogManager.InitLogger( Const.Settings.LogsFolder );\n            AppDomain.CurrentDomain.AssemblyResolve += AutoResolver;\n            var app = new App\n            {\n                ShutdownMode = ShutdownMode.OnMainWindowClose\n            };\n            app.Run();\n        }\n\n        private static Assembly? AutoResolver( object? sender, ResolveEventArgs eventArgs )\n        {\n            string       dllName;\n            const string resName = \".Resources.\";\n            const string dllExt  = \".dll\";\n\n            var programName       = Assembly.GetExecutingAssembly().GetName().Name;\n            var shortAssemblyName = new AssemblyName( eventArgs.Name ).Name;\n\n            if ( shortAssemblyName.EndsWith( \".resources\" ) )\n                return null;\n\n            switch ( shortAssemblyName )\n            {\n                case \"VirtualDesktop10\":\n                    Logger.Debug( \"[Init]Load VirtualDesktop10.dll\" );\n                    dllName = programName + resName + \"VirtualDesktop10\" + dllExt;\n                    break;\n                case \"VirtualDesktop11\":\n                    var ver = SysInfo.OSVersion;\n                    switch ( ver.Build )\n                    {\n                        case <= 22489:\n                            Logger.Debug( \"[Init]Load VirtualDesktop11.dll 21H2\" );\n                            dllName = programName + resName + \"VirtualDesktop11_21H2.dll\";\n                            break;\n                        case 22621:\n                            Logger.Debug( \"[Init]Load VirtualDesktop11.dll 22H2\" );\n                            dllName = ver.Revision switch\n                            {\n                                < 2215 => programName + resName + \"VirtualDesktop11.dll\",\n                                < 3085 => programName + resName + \"VirtualDesktop11_23H2.dll\",\n                                _ => programName + resName + \"VirtualDesktop11_22H2_3085.dll\"\n                            };\n\n                            break;\n                        case 22631:\n                            Logger.Debug( \"[Init]Load VirtualDesktop11.dll 23H2\" );\n                            if ( ver.Revision >= 3085 )\n                            {\n                                dllName = programName + resName + \"VirtualDesktop11_23H2_3085.dll\";\n                            }\n                            else\n                            {\n                                dllName = programName + resName + \"VirtualDesktop11_23H2.dll\";\n                            }\n\n                            break;\n                        case 26100:\n                            Logger.Debug(\"[Init]Load VirtualDesktop11.dll 24H2\");\n                            if (ver.Revision >= 2152) {\n                                dllName = programName + resName + \"VirtualDesktop11_24H2.dll\";\n                            } else {\n                                dllName = programName + resName + \"VirtualDesktop11_23H2.dll\";\n                            }\n\n                            break;\n                        default:\n                            Logger.Debug( \"[Init]Load VirtualDesktop11.dll 22H2\" );\n                            dllName = programName + resName + \"VirtualDesktop11.dll\";\n                            break;\n                    }\n\n                    break;\n                default:\n                    dllName = programName + resName + shortAssemblyName + dllExt;\n                    break;\n            }\n\n            using var stream      = typeof( Program ).Assembly.GetManifestResourceStream( dllName );\n            var       rawAssembly = new byte[stream.Length];\n            stream.Read( rawAssembly, 0, rawAssembly.Length );\n            // try\n            // {\n            //     var filepath = Path.Combine( AppDomain.CurrentDomain.BaseDirectory, shortAssemblyName + dllExt );\n            //     File.WriteAllBytesAsync( filepath, rawAssembly );\n            // }\n            // catch\n            // {\n            //     // ignored\n            // }\n\n            return Assembly.Load( rawAssembly );\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/Tools/SystemTool.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Windows;\n\nnamespace VirtualSpace.Tools\n{\n    public static class SystemTool\n    {\n        public static bool VersionCheck()\n        {\n            var version = Environment.OSVersion.Version;\n            if ( version is {Major: >= 10, Build: >= 17763 and <= 26200} )\n            {\n                return true;\n            }\n\n            MessageBox.Show( Agent.Langs.GetString( \"VersionCheckFail\" ), @\"Error\" );\n            return false;\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/Tools/TrayIcon.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.Drawing;\nusing System.Drawing.Drawing2D;\nusing System.Drawing.Text;\nusing System.Globalization;\nusing System.Resources;\nusing System.Windows.Forms;\nusing VirtualSpace.Helpers;\nusing ConfigManager = VirtualSpace.Config.Manager;\n\nnamespace VirtualSpace.Tools\n{\n    public static class TrayIcon\n    {\n        private static readonly NotifyIcon         Ti                 = new();\n        private static readonly ContextMenuStrip   TiMenu             = new();\n        private static readonly ToolStripMenuItem  TraySettings       = new();\n        private static readonly ToolStripSeparator ToolStripSeparator = new();\n        private static readonly ToolStripMenuItem  TrayQuit           = new();\n        private static readonly ResourceManager    ImageManager       = Agent.Images;\n\n        static TrayIcon()\n        {\n            SetLang();\n            InitTrayIcon();\n\n            TraySettings.Click += ( sender, args ) => { MainWindow.AcForm.BringToTop(); };\n            TrayQuit.Click += ( sender,     args ) => { MainWindow.Quit(); };\n\n            TiMenu.Items.AddRange( new ToolStripItem[] {TraySettings, ToolStripSeparator, TrayQuit} );\n            Ti.ContextMenuStrip = TiMenu;\n        }\n\n        public static void InitTrayIcon()\n        {\n            Ti.Icon = Images.BytesToIcon( ImageManager.GetObject( \"TrayIcon\" ) );\n        }\n\n        public static void UpdateVDIndexOnTrayIcon( string index )\n        {\n            if ( ConfigManager.Configs.Cluster.StyleOfVDIndexOnTrayIcon == 0 || index.Length > 2 )\n            {\n                PaintVdIndexWithLogo( index );\n                return;\n            }\n\n            var backColor   = \"TrayIconBack_White\";\n            var numberColor = \"Black\";\n            switch ( ConfigManager.Configs.Cluster.StyleOfVDIndexOnTrayIcon )\n            {\n                case 1:\n                    backColor = \"TrayIconBack_White\";\n                    numberColor = \"Black\";\n                    break;\n                case 2:\n                    backColor = \"TrayIconBack_Black\";\n                    numberColor = \"White\";\n                    break;\n            }\n\n            using var bitmap = Images.BytesToBitmap( ImageManager.GetObject( $@\"{backColor}\" ) );\n            if ( index.Length == 1 )\n            {\n                using var number = Images.BytesToBitmap( ImageManager.GetObject( $@\"Big{index}{numberColor}\" ) );\n                using var gBack  = Graphics.FromImage( bitmap );\n                gBack.CompositingMode = CompositingMode.SourceOver;\n                number.MakeTransparent();\n                gBack.DrawImage( number, new Point( 0, 0 ) );\n            }\n            else\n            {\n                using var number1 = Images.BytesToBitmap( ImageManager.GetObject( $@\"Small{index[0]}{numberColor}\" ) );\n                using var number2 = Images.BytesToBitmap( ImageManager.GetObject( $@\"Small{index[1]}{numberColor}\" ) );\n                number1.MakeTransparent();\n                number2.MakeTransparent();\n                using var gBack = Graphics.FromImage( bitmap );\n                gBack.CompositingMode = CompositingMode.SourceOver;\n                gBack.DrawImage( number1, new Point( 0, 0 ) );\n                gBack.DrawImage( number2, new Point( bitmap.Width / 2, 0 ) );\n            }\n\n            Ti.Icon = Icon.FromHandle( bitmap.GetHicon() );\n        }\n\n        private static void PaintVdIndexWithLogo( string index )\n        {\n            using var bitmap = Images.BytesToBitmap( ImageManager.GetObject( \"TrayIconBack_Default\" ) );\n            var       rectF  = new RectangleF( 0, 0, bitmap.Width, bitmap.Height );\n            var textFormat = new StringFormat\n            {\n                Alignment = StringAlignment.Center,\n                LineAlignment = StringAlignment.Center\n            };\n\n            var fontSize   = 210;\n            var borderSize = 10;\n\n            switch ( index.Length )\n            {\n                case 1:\n                    fontSize = 210;\n                    borderSize = 20;\n                    break;\n                case 2:\n                    fontSize = 160;\n                    borderSize = 30;\n                    break;\n                case 3:\n                    fontSize = 110;\n                    borderSize = 30;\n                    break;\n            } // fontSize and borderSize based on TrayIconBack_Default's size is 256x256\n\n            using var textFont  = new Font( \"Comic Sans MS\", fontSize, FontStyle.Bold, GraphicsUnit.Pixel );\n            using var textBrush = new SolidBrush( ColorTranslator.FromHtml( \"#FFFFFF\" ) );\n            using var borderPen = new Pen( ColorTranslator.FromHtml( \"#FF0000\" ), borderSize );\n            borderPen.LineJoin = LineJoin.Round; // prevent \"spikes\" at the path\n\n            using var gp = new GraphicsPath();\n            gp.AddString( index, textFont.FontFamily, (int)textFont.Style, textFont.Size, rectF, textFormat );\n\n            using var g = Graphics.FromImage( bitmap );\n            g.SmoothingMode = SmoothingMode.AntiAlias;\n            g.InterpolationMode = InterpolationMode.HighQualityBicubic;\n            g.PixelOffsetMode = PixelOffsetMode.HighQuality;\n            g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;\n\n            g.DrawPath( borderPen, gp );\n            g.FillPath( textBrush, gp );\n\n            g.Flush();\n\n            Ti.Icon = Icon.FromHandle( bitmap.GetHicon() );\n        }\n\n        public static void SetLang()\n        {\n            CultureInfo.CurrentCulture = new CultureInfo( ConfigManager.CurrentProfile.UI.Language );\n            CultureInfo.CurrentUICulture = new CultureInfo( ConfigManager.CurrentProfile.UI.Language );\n            TraySettings.Text = Agent.Langs.GetString( \"Tray.Menu.Settings\" );\n            TrayQuit.Text = Agent.Langs.GetString( \"Tray.Menu.Quit\" );\n        }\n\n        public static void Show()\n        {\n            Ti.Visible = true;\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/Tools/WindowTool.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Runtime.InteropServices;\nusing System.Windows.Forms;\nusing VirtualSpace.AppLogs;\nusing VirtualSpace.Helpers;\nusing VirtualSpace.VirtualDesktop.Api;\n\nnamespace VirtualSpace.Tools\n{\n    public static class WindowTool\n    {\n        private static void MoveWindowToScreen( IntPtr hWnd, Screen destScreen )\n        {\n            var srcScreen = Screen.FromHandle( hWnd );\n            if ( srcScreen.DeviceName == destScreen.DeviceName ) return;\n\n            var wp = new WINDOWPLACEMENT();\n            wp.Length = Marshal.SizeOf( wp );\n            if ( !User32.GetWindowPlacement( hWnd, ref wp ) ) return;\n\n            var rect = wp.NormalPosition;\n            var targetX = destScreen.WorkingArea.X + rect.Left - srcScreen.WorkingArea.Left;\n            var targetY = destScreen.WorkingArea.Y + rect.Top - srcScreen.WorkingArea.Top;\n            var targetWidth = rect.Right - rect.Left;\n            var targetHeight = rect.Bottom - rect.Top;\n\n            switch ( wp.ShowCmd )\n            {\n                case ShowState.SW_SHOWMAXIMIZED:\n                    _ = User32.ShowWindow( hWnd, (short)ShowState.SW_RESTORE );\n                    User32.SetWindowPos( hWnd, IntPtr.Zero,\n                        targetX, targetY, targetWidth, targetHeight, 0 );\n                    _ = User32.ShowWindow( hWnd, (short)ShowState.SW_MAXIMIZE );\n                    break;\n                case ShowState.SW_MINIMIZE:\n                case ShowState.SW_SHOWMINIMIZED:\n                    _ = User32.ShowWindow( hWnd, (short)ShowState.SW_RESTORE );\n                    User32.SetWindowPos( hWnd, IntPtr.Zero,\n                        targetX, targetY, targetWidth, targetHeight, 0 );\n                    // User32.ShowWindow( mi.Vw.Handle, (short)ShowState.SW_SHOWMINIMIZED );\n                    break;\n                case ShowState.SW_NORMAL:\n                    User32.SetWindowPos( hWnd, IntPtr.Zero,\n                        targetX, targetY, targetWidth, targetHeight, 0 );\n                    break;\n            }\n        }\n\n        public static void MoveWindowToScreen( IntPtr hWnd, int index )\n        {\n            var allScreens = Screen.AllScreens;\n\n            if ( index < 0 || index > allScreens.Length ) return;\n\n            MoveWindowToScreen( hWnd, allScreens[index] );\n        }\n\n        public static void MoveWindowToScreen( IntPtr hWnd, string deviceName )\n        {\n            var allScreens = Screen.AllScreens;\n            var index = -1;\n\n            for ( var i = 0; i < allScreens.Length; i++ )\n            {\n                if ( deviceName == allScreens[i].DeviceName )\n                {\n                    index = i;\n                    break;\n                }\n            }\n\n            if ( index < 0 ) return;\n\n            MoveWindowToScreen( hWnd, allScreens[index] );\n        }\n\n        public static int GetZOrderByHandle( IntPtr hWnd )\n        {\n            var index = 0;\n            _ = User32.EnumWindows( ( wnd, param ) =>\n            {\n                index++;\n                return hWnd != wnd;\n            }, 0 );\n\n            return index;\n        }\n\n        public static void ActiveWindow( IntPtr hWnd, int desktopIndex )\n        {\n            if ( DesktopWrapper.CurrentIndex != desktopIndex )\n            {\n                Logger.Verbose( $\"CHANGE CURRENT DESKTOP TO Desktop[{desktopIndex.ToString()}]\" );\n                DesktopWrapper.MakeVisibleByIndex( desktopIndex );\n            }\n\n            try\n            {\n                Logger.Verbose( \"Try SwitchToThisWindow\" );\n                User32.SwitchToThisWindow( hWnd, true );\n                Logger.Verbose( \"SwitchToThisWindow success.\" );\n            }\n            catch\n            {\n                ActiveWindowReserve( hWnd );\n            }\n        }\n\n        public static void ActiveWindow( IntPtr hWnd, Guid guid )\n        {\n            if ( DesktopWrapper.CurrentGuid != guid )\n            {\n                var sysIndex = DesktopWrapper.IndexFromGuid( guid );\n                Logger.Verbose( $\"CHANGE CURRENT DESKTOP TO Desktop[{sysIndex.ToString()}]\" );\n                DesktopWrapper.MakeVisibleByGuid( guid, false );\n            }\n\n            try\n            {\n                Logger.Verbose( \"Try SwitchToThisWindow\" );\n                User32.SwitchToThisWindow( hWnd, true );\n                Logger.Verbose( \"SwitchToThisWindow success.\" );\n            }\n            catch\n            {\n                ActiveWindowReserve( hWnd );\n            }\n        }\n\n        private static void ActiveWindowReserve( IntPtr hWnd )\n        {\n            if ( User32.IsIconic( hWnd ) )\n            {\n                _ = User32.ShowWindow( hWnd, (short)ShowState.SW_RESTORE );\n            }\n            else\n            {\n                User32.SetForegroundWindow( hWnd );\n                User32.BringWindowToTop( hWnd );\n            }\n        }\n\n        public static bool IsModalWindow( IntPtr hWnd )\n        {\n            // child windows cannot have owners\n            var style = User32.GetWindowLong( hWnd, (int)GetWindowLongFields.GWL_STYLE );\n            if ( ( style & (int)WindowStyles.WS_CHILD ) > 0 ) return false;\n\n            var hWndOwner = User32.GetWindow( hWnd, GetWindowType.GW_OWNER );\n            if ( hWndOwner == IntPtr.Zero ) return false; // not an owned window\n            if ( User32.IsWindowEnabled( hWndOwner ) ) return false; // owner is enabled\n            return true; // an owned window whose owner is disabled\n        }\n\n        public static bool IsPopupToolWindow( IntPtr hWnd )\n        {\n            var style = (uint)User32.GetWindowLong( hWnd, (int)GetWindowLongFields.GWL_STYLE );\n            return style == 0x96000000; // WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/VirtualDesktop/Daemon.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Diagnostics;\nusing System.Globalization;\nusing System.Linq;\nusing System.Text;\nusing System.Threading;\nusing System.Threading.Channels;\nusing System.Threading.Tasks;\nusing VirtualSpace.AppLogs;\nusing VirtualSpace.Commons;\nusing VirtualSpace.Config;\nusing VirtualSpace.Config.Events.Entity;\nusing VirtualSpace.Config.Events.Expression;\nusing VirtualSpace.Helpers;\nusing VirtualSpace.Tools;\nusing VirtualSpace.VirtualDesktop.Api;\nusing ConfigManager = VirtualSpace.Config.Manager;\n\nnamespace VirtualSpace.VirtualDesktop\n{\n    internal static class Daemon\n    {\n        private static int _runlevel = 1;\n        private static readonly ManualResetEvent CanRun = new( false );\n        private static readonly StringBuilder SbWinInfo = new( Const.WindowTitleMaxLength );\n        private static readonly Channel<Behavior> ActionConsumer = Channels.ActionChannel;\n        private static readonly Channel<Window> VisibleWindowsProducer = Channels.VisibleWindowsChannel;\n\n        private static async void WaitForAction()\n        {\n            while ( await ActionConsumer.Reader.WaitToReadAsync() )\n            {\n                if ( !ActionConsumer.Reader.TryRead( out var action ) ) continue;\n\n                if ( action.HideFromView )\n                {\n                    Logger.Debug( $\"[RULE.Action]HIDE.Win {action.Handle.ToString( \"X2\" )}\" );\n                    Filters.WndHandleIgnoreListByManual.TryAdd( action.Handle, 0 );\n                }\n\n                if ( action.MoveToScreen >= 0 )\n                {\n                    Logger.Debug( $\"[RULE.Action]MOVE_TO_SCREEN.Win {action.Handle.ToString( \"X2\" )} TO Screen[{action.MoveToScreen.ToString()}]\" );\n                    WindowTool.MoveWindowToScreen( action.Handle, action.MoveToScreen );\n                }\n\n                if ( action.PinApp )\n                {\n                    Logger.Debug( $\"[RULE.Action]PIN.App of {action.Handle.ToString( \"X2\" )} TO All Desktops\" );\n                    try\n                    {\n                        DesktopWrapper.PinApp( action.Handle, false );\n                    }\n                    catch\n                    {\n                        Logger.Error( $\"[RULE.Action]PIN.App {action.Handle.ToString( \"X2\" )} Failed\" );\n                    }\n\n                    continue; // <- if PinApp, then PinWindow & MoveToDesktop is invalid\n                }\n\n                if ( action.PinWindow )\n                {\n                    Logger.Debug( $\"[RULE.Action]PIN.Win {action.Handle.ToString( \"X2\" )} TO All Desktops\" );\n                    try\n                    {\n                        DesktopWrapper.PinWindow( action.Handle, false );\n                    }\n                    catch\n                    {\n                        Logger.Error( $\"[RULE.Action]PIN.Win {action.Handle.ToString( \"X2\" )} Failed\" );\n                    }\n\n                    continue; // <- if PinWindow, then MoveToDesktop is invalid\n                }\n\n                if ( action.MoveToDesktop >= 0 )\n                {\n                    try\n                    {\n                        Logger.Debug( $\"[RULE.Action]MOVE.Win {action.Handle.ToString( \"X2\" )} TO Desktop[{action.MoveToDesktop.ToString()}]\" );\n                        DesktopWrapper.MoveWindowToDesktop( action.Handle, action.MoveToDesktop );\n                        if ( action.FollowWindow )\n                        {\n                            WindowTool.ActiveWindow( action.Handle, action.MoveToDesktop );\n                        }\n                    }\n                    catch\n                    {\n                        CultureInfo.CurrentUICulture = new CultureInfo( ConfigManager.CurrentProfile.UI.Language );\n                        Logger.Error(\n                            $\"[RULE.Action]MOVE.Win {action.Handle.ToString( \"X2\" )} TO Desktop[{action.MoveToDesktop.ToString()}]\",\n                            new NotifyObject\n                            {\n                                Title = Agent.Langs.GetString( \"Error.Title\" ),\n                                Message = string.Format( Agent.Langs.GetString( \"Error.MoveWindowToDesktop\" ), action.WindowTitle, action.RuleName )\n                            } );\n                    }\n                }\n            }\n        }\n\n        public static async void Start()\n        {\n            WaitForAction();\n            StartDaemon();\n            if ( ConfigManager.CurrentProfile.DaemonAutoStart )\n            {\n                if ( ConfigManager.CurrentProfile.DaemonAutoStartDelay > 0 )\n                    await Task.Delay( ConfigManager.CurrentProfile.DaemonAutoStartDelay * Const.OneSecond );\n                CanRun.Set();\n            }\n        }\n\n        public static void SetCanRun( bool isCanRun )\n        {\n            if ( isCanRun )\n            {\n                CanRun.Set();\n            }\n            else\n            {\n                CanRun.Reset();\n            }\n        }\n\n        public static void SetRunLevel( int i )\n        {\n            _runlevel = i < 1 ? 1 : i;\n        }\n\n        private static void StartDaemon()\n        {\n            Task.Factory.StartNew( () =>\n            {\n                var sw = Stopwatch.StartNew();\n                while ( true )\n                {\n                    CanRun.WaitOne();\n                    _ = User32.EnumWindows( WindowHandleFilter, 0 );\n                    if ( sw.ElapsedMilliseconds >= Const.OneMinute )\n                    {\n                        Logger.Debug( \"Daemon running normally in last minute.\" );\n                        sw.Restart();\n                    }\n\n                    Thread.Sleep( _runlevel * Const.OneSecond );\n                }\n            }, TaskCreationOptions.LongRunning );\n        }\n\n        private static bool WindowHandleFilter( IntPtr hWnd, int lParam )\n        {\n            if ( Conditions.WndHandleIgnoreListByRule.Contains( hWnd ) ||\n                 Filters.WndHandleIgnoreListByError.Contains( hWnd ) ||\n                 !User32.IsWindowVisible( hWnd ) ||\n                 Filters.IsCloaked( hWnd ) )\n                return true;\n\n            _ = User32.GetWindowText( hWnd, SbWinInfo, SbWinInfo.Capacity );\n            var title = SbWinInfo.ToString();\n            if ( string.IsNullOrEmpty( title ) ||\n                 Filters.WndTitleIgnoreList.Contains( title ) )\n                return true;\n\n            _ = User32.GetClassName( hWnd, SbWinInfo, SbWinInfo.Capacity );\n            var classname = SbWinInfo.ToString();\n            if ( Filters.WndClsIgnoreList.Contains( classname ) )\n                return true;\n\n            switch ( classname )\n            {\n                case \"#32770\" when WindowTool.IsModalWindow( hWnd ):\n                case \"Chrome_WidgetWin_1\" or \"MozillaDropShadowWindowClass\" when WindowTool.IsPopupToolWindow( hWnd ):\n                    return true;\n            }\n\n            if ( classname != Const.WindowsUiCoreWindow )\n            {\n                SendToCheckingRule( hWnd, title, classname );\n            }\n\n            return true;\n        }\n\n        private static void SendToCheckingRule( IntPtr hWnd, string title, string classname )\n        {\n            VisibleWindowsProducer.Writer.TryWrite( new Window { Title = title, WndClass = classname, Handle = hWnd } );\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/VirtualDesktop/DragWindow.Designer.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nnamespace VirtualSpace.VirtualDesktop\n{\n    partial class DragWindow\n    {\n        /// <summary>\n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose( bool disposing )\n        {\n            if ( disposing && ( components != null ) ) {\n                components.Dispose();\n            }\n            base.Dispose( disposing );\n        }\n\n        #region Windows Form Designer generated code\n\n        /// <summary>\n        /// Required method for Designer support - do not modify\n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            this.SuspendLayout();\n            // \n            // DragWindow\n            // \n            this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.BackColor = System.Drawing.Color.Black;\n            this.ClientSize = new System.Drawing.Size(800, 450);\n            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;\n            this.Name = \"DragWindow\";\n            this.TransparencyKey = System.Drawing.Color.Black;\n            this.ResumeLayout(false);\n\n        }\n\n        #endregion\n    }\n}"
  },
  {
    "path": "VirtualSpace/VirtualDesktop/DragWindow.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Windows.Forms;\nusing VirtualSpace.Config;\n\nnamespace VirtualSpace.VirtualDesktop\n{\n    public partial class DragWindow : Form\n    {\n        private DragWindow()\n        {\n            InitializeComponent();\n        }\n\n        public IntPtr Thumb { get; set; }\n\n        public static DragWindow CreateAndShow( int width, int height )\n        {\n            var dw = new DragWindow();\n            dw.TopLevel = true;\n            dw.TopMost = true;\n            dw.ShowInTaskbar = false;\n            dw.Width = width;\n            dw.Height = height;\n            dw.Text = Const.Window.VD_DRAG_TITLE;\n            dw.Show();\n            return dw;\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/VirtualDesktop/DragWindow.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n    <!-- \n      Microsoft ResX Schema \n      \n      Version 2.0\n      \n      The primary goals of this format is to allow a simple XML format \n      that is mostly human readable. The generation and parsing of the \n      various data types are done through the TypeConverter classes \n      associated with the data types.\n      \n      Example:\n      \n      ... ado.net/XML headers & schema ...\n      <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n      <resheader name=\"version\">2.0</resheader>\n      <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n      <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n      <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n      <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n      <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n          <value>[base64 mime encoded serialized .NET Framework object]</value>\n      </data>\n      <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n          <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n          <comment>This is a comment</comment>\n      </data>\n                  \n      There are any number of \"resheader\" rows that contain simple \n      name/value pairs.\n      \n      Each data row contains a name, and value. The row also contains a \n      type or mimetype. Type corresponds to a .NET class that support \n      text/value conversion through the TypeConverter architecture. \n      Classes that don't support this are serialized and stored with the \n      mimetype set.\n      \n      The mimetype is used for serialized objects, and tells the \n      ResXResourceReader how to depersist the object. This is currently not \n      extensible. For a given mimetype the value must be set accordingly:\n      \n      Note - application/x-microsoft.net.object.binary.base64 is the format \n      that the ResXResourceWriter will generate, however the reader can \n      read any of the formats listed below.\n      \n      mimetype: application/x-microsoft.net.object.binary.base64\n      value   : The object must be serialized with \n              : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n              : and then encoded with base64 encoding.\n      \n      mimetype: application/x-microsoft.net.object.soap.base64\n      value   : The object must be serialized with \n              : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n              : and then encoded with base64 encoding.\n  \n      mimetype: application/x-microsoft.net.object.bytearray.base64\n      value   : The object must be serialized into a byte array \n              : using a System.ComponentModel.TypeConverter\n              : and then encoded with base64 encoding.\n      -->\n    <xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\" id=\"root\" xmlns=\"\">\n        <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\"/>\n        <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n            <xsd:complexType>\n                <xsd:choice maxOccurs=\"unbounded\">\n                    <xsd:element name=\"metadata\">\n                        <xsd:complexType>\n                            <xsd:sequence>\n                                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\"/>\n                            </xsd:sequence>\n                            <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\"/>\n                            <xsd:attribute name=\"type\" type=\"xsd:string\"/>\n                            <xsd:attribute name=\"mimetype\" type=\"xsd:string\"/>\n                            <xsd:attribute ref=\"xml:space\"/>\n                        </xsd:complexType>\n                    </xsd:element>\n                    <xsd:element name=\"assembly\">\n                        <xsd:complexType>\n                            <xsd:attribute name=\"alias\" type=\"xsd:string\"/>\n                            <xsd:attribute name=\"name\" type=\"xsd:string\"/>\n                        </xsd:complexType>\n                    </xsd:element>\n                    <xsd:element name=\"data\">\n                        <xsd:complexType>\n                            <xsd:sequence>\n                                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\"/>\n                                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\"/>\n                            </xsd:sequence>\n                            <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\"/>\n                            <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\"/>\n                            <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\"/>\n                            <xsd:attribute ref=\"xml:space\"/>\n                        </xsd:complexType>\n                    </xsd:element>\n                    <xsd:element name=\"resheader\">\n                        <xsd:complexType>\n                            <xsd:sequence>\n                                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\"/>\n                            </xsd:sequence>\n                            <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\"/>\n                        </xsd:complexType>\n                    </xsd:element>\n                </xsd:choice>\n            </xsd:complexType>\n        </xsd:element>\n    </xsd:schema>\n    <resheader name=\"resmimetype\">\n        <value>text/microsoft-resx</value>\n    </resheader>\n    <resheader name=\"version\">\n        <value>2.0</value>\n    </resheader>\n    <resheader name=\"reader\">\n        <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n    </resheader>\n    <resheader name=\"writer\">\n        <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n    </resheader>\n</root>"
  },
  {
    "path": "VirtualSpace/VirtualDesktop/Filters.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Collections.Generic;\nusing System.Collections.Concurrent;\nusing VirtualSpace.Config;\nusing VirtualSpace.Helpers;\n\nnamespace VirtualSpace.VirtualDesktop\n{\n    public static class Filters\n    {\n        public static readonly string[] WndClsIgnoreList =\n        {\n            \"Progman\",\n            \"RainmeterMeterWindow\",\n            \"SysDragImage\",\n            \"DuiMenuWnd\",\n            \"PerryShadowWnd\",\n            \"SysShadow\"\n        };\n\n        public static readonly string[] WndTitleIgnoreList =\n        {\n            Const.Window.VD_FRAME_TITLE,\n            Const.Window.VD_CONTAINER_TITLE,\n            Const.Window.VD_DRAG_TITLE,\n            Const.Window.VS_CONTROLLER_TITLE,\n            Const.Window.VS_WINDOW_FILTER_TITLE,\n            \"WinFormsDesigner\"\n        };\n\n        public static readonly List<IntPtr> WndHandleIgnoreListByError = new();\n        public static readonly ConcurrentDictionary<IntPtr, int> WndHandleIgnoreListByManual = new();\n\n        public static bool IsCloaked( IntPtr handle )\n        {\n            var HRESULT = DwmApi.DwmGetWindowAttribute( handle,\n                (uint)DwmApi.DwmWindowAttribute.DWMWA_CLOAKED,\n                out var cloaked,\n                sizeof( uint ) );\n\n            return cloaked > 2;\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/VirtualDesktop/Manager.arrangement.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing VirtualSpace.VirtualDesktop.Api;\nusing ConfigManager = VirtualSpace.Config.Manager;\n\nnamespace VirtualSpace.VirtualDesktop\n{\n    internal static partial class VirtualDesktopManager\n    {\n        public static int GetMatrixIndexByVdIndex( int vdIndex )\n        {\n            var rowsCols    = (int)Math.Ceiling( Math.Sqrt( DesktopWrapper.Count ) );\n            var rc          = Navigation.RowColFromIndex( rowsCols, vdIndex, ConfigManager.CurrentProfile.UI.DesktopArrangement );\n            var matrixIndex = Navigation.IndexFromRowCol( rowsCols, rc, 0 );\n\n            return matrixIndex;\n        }\n\n        public static int GetVdIndexByMatrixIndex( int matrixIndex )\n        {\n            var rowsCols = (int)Math.Ceiling( Math.Sqrt( DesktopWrapper.Count ) );\n            var rc       = Navigation.RowColFromIndex( rowsCols, matrixIndex, 0 );\n            var vdIndex  = Navigation.IndexFromRowCol( rowsCols, rc, ConfigManager.CurrentProfile.UI.DesktopArrangement );\n\n            return vdIndex;\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/VirtualDesktop/Manager.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing VirtualSpace.AppLogs;\nusing VirtualSpace.Config;\nusing VirtualSpace.Helpers;\nusing VirtualSpace.VirtualDesktop.Api;\n\nnamespace VirtualSpace.VirtualDesktop\n{\n    internal static partial class VirtualDesktopManager\n    {\n        private static readonly List<VisibleWindow>        VisibleWindows   = new();\n        private static readonly User32.EnumWindowsProc     EnumWindowsProc  = VisibleWindowFilter;\n        private static readonly StringBuilder              SbWinInfo        = new( Const.WindowTitleMaxLength );\n        private static          List<VirtualDesktopWindow> _virtualDesktops = new();\n        public static           bool                       IsBatchCreate { get; set; }\n        public static           Guid                       LastDesktopId = Guid.Empty;\n\n        private static bool VisibleWindowFilter( IntPtr hWnd, int lParam )\n        {\n            if ( Filters.WndHandleIgnoreListByError.Contains( hWnd ) ||\n                 Filters.WndHandleIgnoreListByManual.TryGetValue( hWnd, out _ ) ||\n                 !User32.IsWindowVisible( hWnd ) ||\n                 Filters.IsCloaked( hWnd ) )\n                return true;\n\n            _ = User32.GetWindowText( hWnd, SbWinInfo, SbWinInfo.Capacity );\n            var title = SbWinInfo.ToString();\n            if ( string.IsNullOrEmpty( title ) ||\n                 Filters.WndTitleIgnoreList.Contains( title ) )\n                return true;\n\n            _ = User32.GetClassName( hWnd, SbWinInfo, SbWinInfo.Capacity );\n            var classname = SbWinInfo.ToString();\n            if ( Filters.WndClsIgnoreList.Contains( classname ) )\n                return true;\n\n            if ( classname != Const.WindowsUiCoreWindow )\n            {\n                VisibleWindows.Add( new VisibleWindow( title, classname, hWnd ) );\n            }\n\n            return true;\n        }\n\n        private static List<VisibleWindow> GetVisibleWindows()\n        {\n            VisibleWindows.Clear();\n            _ = User32.EnumWindows( EnumWindowsProc, 0 );\n            return VisibleWindows;\n        }\n\n        public static void ShowVisibleWindowsForDesktops( List<VirtualDesktopWindow>? vdwList = null, int processId = 0 )\n        {\n            var visibleWindows = GetVisibleWindows();\n            Logger.Debug( $\"VisibleWindows/ApplicationViews: {visibleWindows.Count.ToString()}/{DesktopManagerWrapper.GetViewCount().ToString()}\" );\n\n            vdwList ??= _virtualDesktops;\n\n            foreach ( var virtualDesktopWindow in vdwList )\n            {\n                virtualDesktopWindow.ClearVisibleWindows();\n            }\n\n            foreach ( var win in visibleWindows )\n            {\n                try\n                {\n                    if ( processId != 0 )\n                    {\n                        _ = User32.GetWindowThreadProcessId( win.Handle, out var pId );\n                        if ( processId != pId ) continue;\n                    }\n\n                    if ( DesktopWrapper.IsWindowPinned( win.Handle ) ||\n                         DesktopWrapper.IsApplicationPinned( win.Handle ) )\n                    {\n                        Logger.Debug( $\"{win.Title} IS PINNED\" );\n                        foreach ( var vdw in _virtualDesktops )\n                            vdw.AddWindow( new VisibleWindow( win.Title, win.Classname, win.Handle ) );\n                        continue;\n                    }\n\n                    var ownerId = DesktopWrapper.GuidFromWindow( win.Handle );\n                    if ( vdwList.Count == _virtualDesktops.Count ) // show for all VDs\n                    {\n                        var owner = vdwList.Find( v => v.VdId == ownerId );\n                        if ( owner is null ) continue;\n                        owner.AddWindow( win );\n                        Logger.Debug( $\"Desktop[{owner.VdIndex.ToString()}]({DesktopWrapper.DesktopNameFromIndex( owner.VdIndex )}) CONTAINS {win.Title}\" );\n                    }\n                    else // show for specific VDs\n                    {\n                        foreach ( var vdw in vdwList.Where( vdw => vdw.VdId == ownerId ) )\n                        {\n                            vdw.AddWindow( win );\n                            Logger.Debug( $\"Desktop[{vdw.VdIndex.ToString()}]({DesktopWrapper.DesktopNameFromIndex( vdw.VdIndex )}) CONTAINS {win.Title}\" );\n                        }\n                    }\n                }\n                catch ( Exception ex )\n                {\n                    if ( win.Classname != Const.ApplicationFrameWindow )\n                    {\n                        Logger.Warning( $\"{ex.Message} ∵ {win.Title}({win.Handle.ToString( \"X2\" )}), WndClass: {win.Classname}\" );\n                        Filters.WndHandleIgnoreListByError.Add( win.Handle );\n                    }\n                }\n            }\n\n            foreach ( var vdw in vdwList )\n            {\n                vdw.ShowThumbnails();\n            }\n        }\n\n        public static void RefreshThumbs( IntPtr h, params VirtualDesktopWindow[] vdwList )\n        {\n            if ( DesktopWrapper.IsWindowPinned( h ) ||\n                 DesktopWrapper.IsApplicationPinned( h ) )\n            {\n                ShowVisibleWindowsForDesktops();\n            }\n            else\n            {\n                ShowVisibleWindowsForDesktops( vdwList.ToList() );\n            }\n        }\n\n        public static void ShowAllVirtualDesktops()\n        {\n            UpdateVdwBackground();\n            foreach ( var vdw in _virtualDesktops )\n            {\n                User32.SendMessage( vdw.Handle, WinMsg.WM_HOTKEY, UserMessage.ShowVdw, 0 );\n            }\n        }\n\n        public static void HideAllVirtualDesktops()\n        {\n            Menus.CloseContextMenu();\n            foreach ( var vdw in _virtualDesktops )\n            {\n                vdw.ResetOnlyOneStatus();\n                vdw.Hide();\n                vdw.ClearVisibleWindows();\n            }\n        }\n\n        public static List<VirtualDesktopWindow> GetAllVirtualDesktops()\n        {\n            return _virtualDesktops;\n        }\n\n        public static VirtualDesktopWindow GetCurrentVdw()\n        {\n            return _virtualDesktops.Single( v => v.VdId == DesktopWrapper.CurrentGuid );\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/VirtualDesktop/Manager.events.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing System.Windows.Forms;\nusing System.Windows.Media;\nusing Notification.Wpf;\nusing VirtualSpace.AppLogs;\nusing VirtualSpace.Config;\nusing VirtualSpace.Helpers;\nusing VirtualSpace.VirtualDesktop.Api;\nusing ConfigManager = VirtualSpace.Config.Manager;\n\nnamespace VirtualSpace.VirtualDesktop\n{\n    internal static partial class VirtualDesktopManager\n    {\n        public static void RegisterVirtualDesktopEvents()\n        {\n            DesktopManagerWrapper.DesktopCreatedEvent += () =>\n            {\n                if ( !IsBatchCreate ) UpdateMainView();\n            };\n            DesktopManagerWrapper.DesktopDeletedEvent += vdn => { UpdateMainView( vdn: vdn ); };\n            DesktopManagerWrapper.DesktopChangedEvent += vdn =>\n            {\n                LastDesktopId = vdn.OldId;\n                if ( MainWindow.IsShowing() )\n                    UpdateVdwBackground();\n\n                if ( ConfigManager.Configs.Cluster.NotificationOnVdChanged )\n                {\n                    CultureInfo.CurrentUICulture = new CultureInfo( ConfigManager.CurrentProfile.UI.Language );\n                    Logger.Notify( new NotifyObject\n                    {\n                        Title = Agent.Langs.GetString( \"Cluster.Notification.SVD.Current\" ) + DesktopWrapper.DesktopNameFromGuid( vdn.NewId ),\n                        Message = Agent.Langs.GetString( \"Cluster.Notification.SVD.Last\" ) + DesktopWrapper.DesktopNameFromGuid( vdn.OldId ),\n                        Background = new SolidColorBrush( Colors.DarkSlateGray ),\n                        Foreground = new SolidColorBrush( Colors.White ),\n                        Type = NotificationType.Notification,\n                        ExpTime = TimeSpan.FromSeconds( 3 )\n                    } );\n                }\n\n                MainWindow.UpdateVDIndexOnTrayIcon( vdn.NewId );\n            };\n\n            DesktopManagerWrapper.RegisterVirtualDesktopEvents(\n                () =>\n                {\n                    Logger.Event( $\"Wallpaper Changed\" );\n                    Parallel.ForEach( GetAllVirtualDesktops(), ( vdw, _ ) => { vdw.UpdateWallpaper(); } );\n                },\n                ( guid, path ) =>\n                {\n                    var vdwList = GetAllVirtualDesktops();\n                    var vd      = ( from vdw in vdwList where vdw.VdId == guid select vdw ).FirstOrDefault();\n                    if ( vd is null ) return;\n                    vd.UpdateWallpaper();\n                    Logger.Event( $\"Desktop[{vd.VdIndex.ToString()}] Wallpaper Changed: {path}\" );\n                }\n            );\n\n            DesktopWrapper.OnDesktopVisibleEvent += ( desktop, forceFocusForegroundWindow ) =>\n            {\n                if ( MainWindow.IsShowing() )\n                {\n                    desktop.MakeVisible();\n                    return;\n                }\n\n                forceFocusForegroundWindow ??= Manager.Configs.Cluster.ForceFocusForegroundWindow;\n                if ( (bool)forceFocusForegroundWindow )\n                {\n                    var hTaskBar = User32.FindWindow( Const.TaskbarWndClass, \"\" );\n                    if ( hTaskBar == IntPtr.Zero )\n                    {\n                        Logger.Verbose( \"Taskbar not found, switch desktop only.\" );\n                        desktop.MakeVisible();\n                        return;\n                    }\n\n                    if ( SysInfo.IsTaskbarVisible() )\n                    {\n                        User32.SetForegroundWindow( hTaskBar );\n                        desktop.MakeVisible();\n\n                        if ( User32.GetForegroundWindow() != hTaskBar )\n                        {\n                            Logger.Verbose( \"Taskbar not active, switch desktop only.\" );\n                            return;\n                        }\n\n                        if ( SysInfo.IsAdministrator )\n                        {\n                            Logger.Verbose( \"Send [Alt+Esc].\" );\n                            LowLevelKeyboardHook.MultipleKeyPress( new List<Keys> {Keys.Menu, Keys.Escape} );\n                        }\n                        else\n                        {\n                            Logger.Verbose( \"Force minimize taskbar.\" );\n                            _ = User32.ShowWindow( hTaskBar, (short)ShowState.SW_FORCEMINIMIZE );\n                        }\n                    }\n                    else\n                    {\n                        Logger.Verbose( \"Taskbar is hiding, switch desktop only.\" );\n                        desktop.MakeVisible();\n                    }\n                }\n                else\n                {\n                    desktop.MakeVisible();\n                }\n            };\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/VirtualDesktop/Manager.layout.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing VirtualSpace.AppLogs;\nusing VirtualSpace.Commons;\nusing VirtualSpace.Config.Entity;\nusing VirtualSpace.Helpers;\nusing VirtualSpace.VirtualDesktop.Api;\nusing ConfigManager = VirtualSpace.Config.Manager;\n\nnamespace VirtualSpace.VirtualDesktop\n{\n    internal static partial class VirtualDesktopManager\n    {\n        private static Color         _vdwDefaultBackColor;\n        public static  UserInterface Ui => ConfigManager.CurrentProfile.UI;\n\n        private static void SyncVirtualDesktops()\n        {\n            var commonSize = GetCommonVdwSize();\n\n            var survivalDesktops = new List<VirtualDesktopWindow>();\n            for ( var index = 0; index < DesktopWrapper.Count; index++ ) // build new list according to current system vd list\n            {\n                var guid = DesktopManagerWrapper.GetIdByIndex( index );\n                if ( guid == default ) continue;\n                var survival = _virtualDesktops.Find( v => v.VdId == guid );\n                if ( survival == null )\n                {\n                    survival = VirtualDesktopWindow.Create( index, guid, commonSize, _vdwDefaultBackColor, Ui.VDWPadding );\n                }\n                else\n                {\n                    survival.VdIndex = index;\n                }\n\n                survivalDesktops.Add( survival );\n            }\n\n            var sysGuids = survivalDesktops.Select( v => v.VdId ).ToList();\n            foreach ( var old in _virtualDesktops.Where( old => !sysGuids.Contains( old.VdId ) ) )\n            {\n                old.RealClose();\n            }\n\n            _virtualDesktops = survivalDesktops; // system vd list order at this moment\n\n            ReOrder(); // reorder by profile\n        }\n\n        private static Size GetCommonVdwSize()\n        {\n            var dpi       = SysInfo.Dpi;\n            var size      = MainWindow.GetCellSizeByMatrixIndex( 0 );\n            var vdwWidth  = ( size.Width - 2 * Ui.VDWBorderSize ) * dpi.ScaleX + 1;\n            var vdwHeight = ( size.Height - 2 * Ui.VDWBorderSize ) * dpi.ScaleY + 1;\n            return new Size( (int)vdwWidth, (int)vdwHeight );\n        }\n\n        private static void ReOrder( bool needSort = false )\n        {\n            if ( needSort )\n                _virtualDesktops.Sort( ( x, y ) => x.VdIndex.CompareTo( y.VdIndex ) );\n\n            var profile  = ConfigManager.CurrentProfile;\n            var sysGuids = _virtualDesktops.Select( vdw => vdw.VdId ).ToList();\n\n            if ( profile.DesktopOrder == null || profile.DesktopOrder.Count == 0 ) // no custom order, using system's\n            {\n                SaveOrder( sysGuids );\n                return;\n            }\n\n            profile.DesktopOrder.RemoveAll( g => !sysGuids.Contains( g ) );\n\n            var orderedByProfile = new List<VirtualDesktopWindow>();\n            for ( var idx = 0; idx < profile.DesktopOrder.Count; idx++ )\n            {\n                var vdw = _virtualDesktops.Find( vdw => vdw.VdId == profile.DesktopOrder[idx] );\n                if ( vdw is null ) continue;\n                vdw.VdIndex = idx; // reposition\n                orderedByProfile.Add( vdw );\n                _virtualDesktops.Remove( vdw );\n            }\n\n            foreach ( var restVdw in _virtualDesktops )\n            {\n                restVdw.VdIndex = orderedByProfile.Count;\n                orderedByProfile.Add( restVdw ); // increase orderedByProfile.Count every turn, so that vdw.VdIndex can be set properly.\n                profile.DesktopOrder.Add( restVdw.VdId ); // append to tail\n            }\n\n            _virtualDesktops = orderedByProfile;\n            SaveOrder();\n        }\n\n        private static void UpdateMainView( VirtualDesktopNotification? vdn = null )\n        {\n            if ( !MainWindow.IsShowing() ) return;\n\n            FixLayout();\n            ShowAllVirtualDesktops();\n\n            if ( vdn is null ) return;\n\n            try\n            {\n                var fallback = _virtualDesktops[GetVdIndexByGuid( vdn.NewId )];\n                ShowVisibleWindowsForDesktops( new List<VirtualDesktopWindow> {fallback} );\n            }\n            catch ( Exception e )\n            {\n                Logger.Warning( \"Update MainView: \" + e.StackTrace );\n            }\n        }\n\n        public static void FixLayout()\n        {\n            try\n            {\n                MainWindow.ResetMainGrid();\n            }\n            catch\n            {\n                MainWindow.NotifyDesktopManagerReset();\n                return;\n            }\n\n            SyncVirtualDesktops();\n        }\n\n        public static async Task InitLayout()\n        {\n            MainWindow.ResetMainGrid();\n\n            var commonSize = GetCommonVdwSize();\n\n            var tasks = new List<Task>();\n            for ( var i = 0; i < DesktopWrapper.Count; i++ )\n            {\n                var index = i;\n                tasks.Add( Task.Run( () =>\n                {\n                    var guid = DesktopManagerWrapper.GetIdByIndex( index );\n                    var vdw  = VirtualDesktopWindow.Create( index, guid, commonSize, _vdwDefaultBackColor, Ui.VDWPadding );\n\n                    lock ( _virtualDesktops ) // thread safe\n                    {\n                        _virtualDesktops.Add( vdw ); // added in random order, need call \"ReOrder( true )\" afterwards\n                    }\n                } ) );\n            }\n\n            try\n            {\n                await Task.WhenAll( tasks.ToArray() );\n            }\n            catch ( Exception ex )\n            {\n                Logger.Error( \"Init Layout: \" + ex.Message );\n                return;\n            }\n\n            ReOrder( true );\n        }\n\n        public static void UpdateVdwBackground()\n        {\n            MainWindow.RenderCellBorder();\n        }\n\n        private static List<Guid> _lastDesktopOrder = new();\n\n        public static void SaveOrder( List<Guid>? newOrder = null )\n        {\n            static bool IsSameGuidList( List<Guid> a, List<Guid> b )\n            {\n                if ( a.Count != b.Count ) return false;\n                return !a.Where( ( t, i ) => t != b[i] ).Any();\n            }\n\n            if ( newOrder != null )\n            {\n                ConfigManager.CurrentProfile.DesktopOrder = newOrder;\n            }\n\n            if ( IsSameGuidList( _lastDesktopOrder, ConfigManager.CurrentProfile.DesktopOrder! ) ) return;\n\n            ConfigManager.Save( reason: \"sync&save\", reasonName: \"ConfigManager.CurrentProfile.DesktopOrder\" );\n            _lastDesktopOrder = new List<Guid>( ConfigManager.CurrentProfile.DesktopOrder! );\n        }\n\n        public static int GetVdIndexByGuid( Guid guid )\n        {\n            return ( from vdw in _virtualDesktops where vdw.VdId == guid select vdw.VdIndex ).FirstOrDefault();\n        }\n\n        public static void Bootstrap()\n        {\n            _vdwDefaultBackColor = Color.FromArgb( Ui.VDWDefaultBackColor.R, Ui.VDWDefaultBackColor.G, Ui.VDWDefaultBackColor.B );\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/VirtualDesktop/Menus.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Drawing;\nusing System.Text;\nusing System.Text.RegularExpressions;\nusing System.Windows.Forms;\nusing VirtualSpace.Config;\nusing VirtualSpace.Helpers;\nusing VirtualSpace.Tools;\nusing VirtualSpace.VirtualDesktop.Api;\n\nnamespace VirtualSpace.VirtualDesktop\n{\n    public static class Menus\n    {\n        private static ContextMenuStrip _ctm;\n\n        public static void ThumbCtm( MenuInfo mi )\n        {\n            _ctm ??= new ContextMenuStrip();\n            _ctm.Items.Clear();\n\n            ////////////////////////////////////////////////////////////////\n            // pin window \n            var pinWindow = new ToolStripMenuItem\n            {\n                Text = Agent.Langs.GetString( \"VDW.CTM.Window.PinWin\" ),\n                Checked = DesktopWrapper.IsWindowPinned( mi.Vw.Handle )\n            };\n            pinWindow.Click += ( s, evt ) =>\n            {\n                DesktopWrapper.PinWindow( mi.Vw.Handle, pinWindow.Checked );\n                VirtualDesktopManager.ShowVisibleWindowsForDesktops();\n            };\n            _ctm.Items.Add( pinWindow );\n\n            ////////////////////////////////////////////////////////////////\n            // pin app\n            var pinApp = new ToolStripMenuItem\n            {\n                Text = Agent.Langs.GetString( \"VDW.CTM.Window.PinApp\" ),\n                Checked = DesktopWrapper.IsApplicationPinned( mi.Vw.Handle )\n            };\n            pinApp.Click += ( s, evt ) =>\n            {\n                DesktopWrapper.PinApp( mi.Vw.Handle, pinApp.Checked );\n                VirtualDesktopManager.ShowVisibleWindowsForDesktops();\n            };\n            _ctm.Items.Add( pinApp );\n\n            ////////////////////////////////////////////////////////////////\n            // hide from view\n            var hideWindow = new ToolStripMenuItem\n            {\n                Text = Agent.Langs.GetString( \"VDW.CTM.Window.HideFromView\" )\n            };\n\n            void OnIgnoreWindowClick( object? s, EventArgs evt )\n            {\n                Filters.WndHandleIgnoreListByManual.TryAdd( mi.Vw.Handle, 0 );\n                VirtualDesktopManager.RefreshThumbs( mi.Vw.Handle, mi.Self );\n            }\n\n            hideWindow.Click += OnIgnoreWindowClick;\n            _ctm.Items.Add( hideWindow );\n\n            _ctm.Items.Add( \"-\" );\n\n            ////////////////////////////////////////////////////////////////\n            // move to screen\n            var itemScreen = new ToolStripMenuItem( Agent.Langs.GetString( \"VDW.CTM.Window.Screen\" ) );\n\n            void MoveToScreen( object? s, EventArgs evt )\n            {\n                var selectedScreen = s as ToolStripMenuItem;\n                WindowTool.MoveWindowToScreen( mi.Vw.Handle, itemScreen.DropDownItems.IndexOf( selectedScreen ) );\n            }\n\n            foreach ( var s in Screen.AllScreens )\n            {\n                var screen = Screen.FromHandle( mi.Vw.Handle );\n                var item   = new ToolStripMenuItem( $\"{s.DeviceName}  ({s.DeviceFriendlyName()})\" );\n                item.Checked = screen.DeviceName == s.DeviceName;\n                item.Click += MoveToScreen;\n                itemScreen.DropDownItems.Add( item );\n            }\n\n            _ctm.Items.Add( itemScreen );\n\n            _ctm.Items.Add( \"-\" );\n\n            ////////////////////////////////////////////////////////////////\n            // rule for window\n            var newRuleFromWindow = new ToolStripMenuItem\n            {\n                Text = Agent.Langs.GetString( \"VDW.CTM.Window.NewRule\" )\n            };\n\n            void OnCreateRuleFromWindow( object? s, EventArgs evt )\n            {\n                MainWindow.AcForm.CreateRuleFromWindowHandle( mi.Vw.Handle );\n            }\n\n            newRuleFromWindow.Click += OnCreateRuleFromWindow;\n            _ctm.Items.Add( newRuleFromWindow );\n\n            _ctm.Items.Add( \"-\" );\n\n            ////////////////////////////////////////////////////////////////\n            // close window \n            var closeWindow = new ToolStripMenuItem\n            {\n                Text = Agent.Langs.GetString( \"VDW.CTM.Window.Close\" )\n            };\n\n            void OnCloseWindowClick( object? s, EventArgs evt )\n            {\n                mi.Self.CloseSelectedWindow( mi.Vw );\n            }\n\n            closeWindow.Click += OnCloseWindowClick;\n            _ctm.Items.Add( closeWindow );\n\n            ////////////////////////////////////////////////////////////////\n            // Show Window ContextMenu \n            _ctm.Show( mi.Sender as Control, mi.Location );\n        }\n\n        public static void VdCtm( MenuInfo mi )\n        {\n            _ctm ??= new ContextMenuStrip();\n            _ctm.Items.Clear();\n\n            //////////////////////////////////////////////////////////////\n            // show & edit desktop's name\n            var sysIndex    = DesktopWrapper.IndexFromGuid( mi.Self.VdId );\n            var currentName = DesktopWrapper.DesktopNameFromIndex( sysIndex );\n            var desktopName = new ToolStripTextBox {Text = currentName, AutoSize = false, Width = 200};\n            desktopName.KeyPress += ( s, evt ) =>\n            {\n                if ( evt.KeyChar != (char)Keys.Enter ) return;\n                if ( currentName != desktopName.Text )\n                {\n                    DesktopWrapper.SetNameByGuid( mi.Self.VdId, desktopName.Text );\n                    mi.Self.UpdateDesktopName( desktopName.Text );\n                }\n\n                evt.Handled = true;\n                _ctm.Close();\n            };\n            _ctm.Items.Add( desktopName );\n\n            _ctm.Items.Add( \"-\" );\n\n            //////////////////////////////////////////////////////////////\n            // UnHideWindow\n            var unHideWindow = new ToolStripMenuItem( Agent.Langs.GetString( \"VDW.CTM.Desktop.UnHideWindow\" ) );\n\n            void OnUnHideWindow( object? s, EventArgs evt )\n            {\n                var item = s as ToolStripMenuItem;\n                var m    = Regex.Match( item.Text, $@\".*{Const.HideWindowSplitter}(.*)\" );\n\n                var h = (IntPtr)int.Parse( m.Groups[1].Value );\n\n                Filters.WndHandleIgnoreListByManual.TryRemove( h, out _ );\n                VirtualDesktopManager.RefreshThumbs( h, mi.Self );\n            }\n\n            var sb = new StringBuilder( Const.WindowTitleMaxLength );\n            foreach ( var handle in Filters.WndHandleIgnoreListByManual.Keys )\n            {\n                if ( !User32.IsWindow( handle ) ) continue;\n                if ( !DesktopWrapper.IsWindowPinned( handle ) &&\n                     !DesktopWrapper.IsApplicationPinned( handle ) &&\n                     DesktopWrapper.GuidFromWindow( handle ) != mi.Self.VdId ) continue;\n\n                _ = User32.GetWindowThreadProcessId( handle, out var pId );\n                var process = Process.GetProcessById( pId );\n\n                _ = User32.GetWindowText( handle, sb, sb.Capacity );\n                var title = sb.ToString();\n\n                var item = new ToolStripMenuItem( $\"[{title}] of {process.ProcessName}(.exe){Const.HideWindowSplitter}{handle}\" );\n                item.Click += OnUnHideWindow;\n                unHideWindow.DropDownItems.Add( item );\n            }\n\n            unHideWindow.Enabled = unHideWindow.DropDownItems.Count > 0;\n            _ctm.Items.Add( unHideWindow );\n\n            _ctm.Items.Add( \"-\" );\n\n            //////////////////////////////////////////////////////////////\n            // delete virtual desktop\n            var delVirtualDesktop = new ToolStripMenuItem( Agent.Langs.GetString( \"VDW.CTM.Desktop.Remove\" ) );\n            delVirtualDesktop.Click += ( s, evt ) =>\n            {\n                if ( DesktopWrapper.RemoveDesktopByGuid( mi.Self.VdId ) )\n                {\n                    var vdw = mi.Self;\n                    vdw.RealClose();\n                    mi.Vdws.RemoveAt( mi.Self.VdIndex );\n                }\n            };\n            _ctm.Items.Add( delVirtualDesktop );\n\n            //////////////////////////////////////////////////////////////\n            // create virtual desktop\n            var createVirtualDesktop = new ToolStripMenuItem( Agent.Langs.GetString( \"VDW.CTM.Desktop.Create\" ) );\n\n            void BatchCreate( object? s, EventArgs evt )\n            {\n                var item  = s as ToolStripMenuItem;\n                var count = int.Parse( item.Text );\n                if ( count > 1 )\n                {\n                    VirtualDesktopManager.IsBatchCreate = true;\n\n                    for ( var i = 0; i < count; i++ )\n                        DesktopWrapper.Create();\n\n                    VirtualDesktopManager.FixLayout();\n                    VirtualDesktopManager.ShowAllVirtualDesktops();\n\n                    VirtualDesktopManager.IsBatchCreate = false;\n                }\n                else\n                {\n                    VirtualDesktopManager.IsBatchCreate = false;\n                    DesktopWrapper.Create();\n                }\n            }\n\n            for ( var i = 1; i <= 10; i++ )\n            {\n                var count = new ToolStripMenuItem( i.ToString() );\n                count.Click += BatchCreate;\n                createVirtualDesktop.DropDownItems.Add( count );\n            }\n\n            _ctm.Items.Add( createVirtualDesktop );\n\n            ///////////////////////////////////\n            // Show Virtual Desktop ContextMenu \n            _ctm.Show( mi.Sender as Control, mi.Location );\n        }\n\n        public static void CloseContextMenu()\n        {\n            _ctm?.Close();\n        }\n    }\n\n    public class MenuInfo\n    {\n        public VisibleWindow              Vw       { get; set; }\n        public VirtualDesktopWindow       Self     { get; set; }\n        public object                     Sender   { get; set; }\n        public Point                      Location { get; set; }\n        public List<VirtualDesktopWindow> Vdws     { get; set; }\n    }\n}"
  },
  {
    "path": "VirtualSpace/VirtualDesktop/Navigation.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Windows.Forms;\nusing VirtualSpace.Config;\n\nnamespace VirtualSpace.VirtualDesktop\n{\n    public static class Navigation\n    {\n        public static int CalculateTargetIndex( int vdCount, int fromIndex, Keys dir, Config.Entity.Navigation nav )\n        {\n            var rowsCols = (int)Math.Ceiling( Math.Sqrt( vdCount ) );\n            var maxIndex = vdCount - 1;\n\n            var da = Manager.CurrentProfile.UI.DesktopArrangement;\n\n            var currentRowCol = RowColFromIndex( rowsCols, fromIndex, da );\n            var targetRowCol  = TargetRowColByDirection( rowsCols, currentRowCol, dir, currentRowCol );\n            var targetIndex   = IndexFromRowCol( rowsCols, targetRowCol, da );\n\n            while ( targetIndex > maxIndex ) // 暴力应对目标桌面不存在的情况\n            {\n                targetRowCol = TargetRowColByDirection( rowsCols, targetRowCol, dir, currentRowCol );\n                targetIndex = IndexFromRowCol( rowsCols, targetRowCol, da );\n            }\n\n            return IndexFromRowCol( rowsCols, targetRowCol, 0 );\n\n            //////////////////////////////////////////////////////////////////////////////////////////////////\n            /// 导航不受 DesktopArrangement 影响，或者说：导航永远按照 DesktopArrarngement 为 0 的情况下进行\n            /// 也即：桌面按照配置文件中的顺序，从左上角开始，行满换行的方式填充到矩阵中\n            /// \n            /// 此函数假设导航的目标桌面一定存在(也就是无法应对桌面数量不是 n 的平方的情况)，若不满足则由单独的代码处理\n            (int R, int C) TargetRowColByDirection( int n, (int R, int C) currentRC, Keys direction, (int R, int C) validRC )\n            {\n                var r         = currentRC.R;\n                var c         = currentRC.C;\n                var targetRow = currentRC.R;\n                var targetCol = currentRC.C;\n\n                switch ( direction )\n                {\n                    case Keys.Left:\n                        if ( c == 0 )\n                        {\n                            if ( nav.CirculationH )\n                            {\n                                if ( nav.CirculationHType == Const.VirtualDesktop.NavHTypeNextRow )\n                                {\n                                    targetRow = r == 0 ? n - 1 : r - 1;\n                                }\n\n                                targetCol = n - 1;\n                            }\n                            else\n                            {\n                                return validRC;\n                            }\n                        }\n                        else\n                        {\n                            targetCol--;\n                        }\n\n                        break;\n                    case Keys.Right:\n                        if ( c == n - 1 )\n                        {\n                            if ( nav.CirculationH )\n                            {\n                                if ( nav.CirculationHType == Const.VirtualDesktop.NavHTypeNextRow )\n                                {\n                                    targetRow = r == n - 1 ? 0 : r + 1;\n                                }\n\n                                targetCol = 0;\n                            }\n                            else\n                            {\n                                return validRC;\n                            }\n                        }\n                        else\n                        {\n                            targetCol++;\n                        }\n\n                        break;\n                    case Keys.Up:\n                        if ( r == 0 )\n                        {\n                            if ( nav.CirculationV )\n                            {\n                                targetRow = n - 1;\n                            }\n                            else\n                            {\n                                return validRC;\n                            }\n                        }\n                        else\n                        {\n                            targetRow--;\n                        }\n\n                        break;\n                    case Keys.Down:\n                        if ( r == n - 1 )\n                        {\n                            if ( nav.CirculationV )\n                            {\n                                targetRow = 0;\n                            }\n                            else\n                            {\n                                return validRC;\n                            }\n                        }\n                        else\n                        {\n                            targetRow++;\n                        }\n\n                        break;\n                }\n\n                return ( targetRow, targetCol );\n            }\n        }\n\n        public static int IndexFromRowCol( int n, (int R, int C) currentRC, int? desktopArrangement )\n        {\n            var r = currentRC.R;\n            var c = currentRC.C;\n            switch ( desktopArrangement )\n            {\n                case 0:\n                    // TopLeft To BottomRight H\n                    return r * n + c;\n                case 1:\n                    // TopRight To BottomLeft H\n                    return r * n + ( n - 1 - c );\n                case 2:\n                    // BottomLeft To TopRight H\n                    return ( n - 1 - r ) * n + c;\n                case 3:\n                    // BottomRight To TopLeft H\n                    return ( n - 1 - r ) * n + ( n - 1 - c );\n                case 4:\n                    // TopLeft To BottomRight V\n                    return c * n + r;\n                case 5:\n                    // TopRight To BottomLeft V\n                    return ( n - 1 - c ) * n + r;\n                case 6:\n                    // BottomLeft To TopRight V\n                    return c * n + ( n - 1 - r );\n                case 7:\n                    // BottomRight To TopLeft V\n                    return ( n - 1 - c ) * n + ( n - 1 - r );\n                default:\n                    // TopLeft To BottomRight H\n                    return r * n + c;\n            }\n        }\n\n        public static (int R, int C) RowColFromIndex( int n, int logicIndex, int? desktopArrangement )\n        {\n            int row, col;\n            switch ( desktopArrangement )\n            {\n                case 0:\n                    // TopLeft To BottomRight H\n                    row = logicIndex / n;\n                    col = logicIndex % n;\n                    break;\n                case 1:\n                    // TopRight To BottomLeft H\n                    row = logicIndex / n;\n                    col = n - 1 - logicIndex % n;\n                    break;\n                case 2:\n                    // BottomLeft To TopRight H\n                    row = n - 1 - logicIndex / n;\n                    col = logicIndex % n;\n                    break;\n                case 3:\n                    // BottomRight To TopLeft H\n                    row = n - 1 - logicIndex / n;\n                    col = n - 1 - logicIndex % n;\n                    break;\n                case 4:\n                    // TopLeft To BottomRight V\n                    row = logicIndex % n;\n                    col = logicIndex / n;\n                    break;\n                case 5:\n                    // TopRight To BottomLeft V\n                    row = logicIndex % n;\n                    col = n - 1 - logicIndex / n;\n                    break;\n                case 6:\n                    // BottomLeft To TopRight V\n                    row = n - 1 - logicIndex % n;\n                    col = logicIndex / n;\n                    break;\n                case 7:\n                    // BottomRight To TopLeft V\n                    row = n - 1 - logicIndex % n;\n                    col = n - 1 - logicIndex / n;\n                    break;\n                default:\n                    // TopLeft To BottomRight H\n                    row = logicIndex / n;\n                    col = logicIndex % n;\n                    break;\n            }\n\n            return ( row, col );\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/VirtualDesktop/VirtualDesktopWindow.Designer.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nnamespace VirtualSpace.VirtualDesktop\n{\n    partial class VirtualDesktopWindow\n    {\n        /// <summary>\n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose( bool disposing )\n        {\n            if ( disposing && ( components != null ) ) {\n                components.Dispose();\n            }\n            ReleaseThumbnails();\n            base.Dispose( disposing );\n        }\n\n        #region Windows Form Designer generated code\n\n        /// <summary>\n        /// Required method for Designer support - do not modify\n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            \n            this.SuspendLayout();\n            // \n            // VirtualDesktopWindow\n            // \n            this.AutoScaleDimensions = new System.Drawing.SizeF(11F, 24F);\n            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            this.ClientSize = new System.Drawing.Size(978, 600);\n            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;\n            this.Name = \"VirtualDesktopWindow\";\n            this.ShowIcon = false;\n            this.ShowInTaskbar = false;\n            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.VirtualDesktopWindow_Closing);\n            this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.VirtualDesktopWindow_MouseDown);\n            this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.VirtualDesktopWindow_MouseMove);\n            this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.VirtualDesktopWindow_MouseUp);\n            this.Paint += new System.Windows.Forms.PaintEventHandler(this.pbWallpaper_Paint);\n            this.ResumeLayout(false);\n\n        }\n\n        #endregion\n\n    }\n}"
  },
  {
    "path": "VirtualSpace/VirtualDesktop/VirtualDesktopWindow.Mouse.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Drawing;\nusing System.Linq;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing System.Windows.Forms;\nusing VirtualSpace.AppLogs;\nusing VirtualSpace.Config;\nusing VirtualSpace.Helpers;\nusing VirtualSpace.Tools;\nusing VirtualSpace.VirtualDesktop.Api;\nusing ConfigManager = VirtualSpace.Config.Manager;\n\nnamespace VirtualSpace.VirtualDesktop\n{\n    public partial class VirtualDesktopWindow\n    {\n        private static int            _hoverVdIndex;\n        private static Point          _startPoint;\n        private static int            _dragState;\n        private static Rectangle      _dragBounds = Rectangle.Empty;\n        private static VisibleWindow? _selectedWindow;\n        private static DragWindow?    _dw;\n        private        bool           _isTheOnlyOneInMainView;\n\n        public void ResetOnlyOneStatus()\n        {\n            _isTheOnlyOneInMainView = false;\n        }\n\n        private void VirtualDesktopWindow_MouseDown( object sender, MouseEventArgs e )\n        {\n            _virtualDesktops = VirtualDesktopManager.GetAllVirtualDesktops();\n            _startPoint = e.Location;\n            var dragSize = SystemInformation.DragSize * ConfigManager.CurrentProfile.Mouse.DragSizeFactor;\n            _dragBounds = new Rectangle(\n                new Point( _startPoint.X - dragSize.Width / 2, _startPoint.Y - dragSize.Height / 2 ),\n                dragSize );\n\n            _selectedWindow = _visibleWindows.FirstOrDefault( w => w.Rect.Contains( e.Location ) );\n            if ( _selectedWindow != null )\n            {\n                Logger.Verbose( \"SELECT.Win \" + _selectedWindow.Title );\n            }\n        }\n\n        private static bool IsOutBounds( Point location )\n        {\n            return _dragBounds != Rectangle.Empty && !_dragBounds.Contains( location );\n        }\n\n        private void VirtualDesktopWindow_MouseMove( object sender, MouseEventArgs e )\n        {\n            if ( _dragState == 0 && e.Button == MouseButtons.Left && IsOutBounds( e.Location ) )\n            {\n                _dragState = 1;\n            }\n\n            if ( _dragState == 0 ) return;\n\n            HoverOnDesktop( sender, e );\n\n            if ( _selectedWindow != null )\n            {\n                if ( _dw == null )\n                {\n                    _dw = DragWindow.CreateAndShow( _selectedWindow.Rect.Width, _selectedWindow.Rect.Height );\n\n                    var i = DwmApi.DwmRegisterThumbnail( _dw.Handle, _selectedWindow.Handle, out var thumb );\n                    if ( i == 0 )\n                    {\n                        var props = new DWM_THUMBNAIL_PROPERTIES\n                        {\n                            fVisible = true,\n                            dwFlags = DwmApi.DWM_TNP_VISIBLE | DwmApi.DWM_TNP_RECTDESTINATION | DwmApi.DWM_TNP_OPACITY,\n                            opacity = 255,\n                            rcDestination = new RECT( 0, 0, _dw.Width, _dw.Height )\n                        };\n                        _dw.Thumb = thumb;\n                        UpdateThumbnail( _dw.Thumb, props );\n                    }\n\n                    var dtp = _selectedWindow.DTP;\n                    dtp.opacity = VirtualDesktopManager.Ui.ThumbDragSourceOpacity;\n                    DwmApi.DwmUpdateThumbnailProperties( _selectedWindow.Thumb, ref dtp );\n                }\n\n                _dw.Left = Cursor.Position.X - _dw.Width / 2;\n                _dw.Top = Cursor.Position.Y - _dw.Height / 2;\n            }\n            else\n            {\n                var vdw = sender as Form;\n                vdw.Left = e.X + vdw.Left - _startPoint.X;\n                vdw.Top = e.Y + vdw.Top - _startPoint.Y;\n            }\n        }\n\n        private void VirtualDesktopWindow_MouseUp( object sender, MouseEventArgs e )\n        {\n            if ( null == sender ) return;\n\n            _hoverVdIndex = HoverOnDesktop( sender, e );\n            if ( _hoverVdIndex < 0 ) return;\n\n            if ( _dragState > 0 )\n            {\n                if ( _selectedWindow != null ) // if we drag a thumbnail in a virtual desktop\n                {\n                    while ( true )\n                    {\n                        _virtualDesktops[_hoverVdIndex].Opacity = 1; // reset hover virtual desktop opacity unconditionally\n\n                        if ( _hoverVdIndex == VdIndex ||\n                             DesktopWrapper.IsWindowPinned( _selectedWindow.Handle ) ||\n                             DesktopWrapper.IsApplicationPinned( _selectedWindow.Handle ) )\n                        {\n                            //////////////////////////\n                            // goes here means no need to move the dragged window\n                            var dtp = _selectedWindow.DTP;\n                            dtp.opacity = 255;\n                            DwmApi.DwmUpdateThumbnailProperties( _selectedWindow.Thumb, ref dtp );\n                            break;\n                        }\n\n                        if ( User32.IsWindow( _selectedWindow.Handle ) )\n                        {\n                            ///////////////////////////\n                            // goes here means the thumbnail window we dragged is drop in another virtual desktop\n                            // we need to move it.\n                            Logger.Verbose( $\"DROP.Win {_selectedWindow.Title}({_selectedWindow.Handle.ToString( \"X2\" )}) IN Desktop[{_hoverVdIndex.ToString()}]\" );\n\n                            var sysIndex = DesktopWrapper.IndexFromGuid( _virtualDesktops[_hoverVdIndex].VdId );\n                            DesktopWrapper.MoveWindowToDesktop( _selectedWindow.Handle, sysIndex );\n\n                            var relevantVirtualDesktops = new List<VirtualDesktopWindow>\n                            {\n                                _virtualDesktops[_hoverVdIndex],\n                                this\n                            };\n                            VirtualDesktopManager.ShowVisibleWindowsForDesktops( relevantVirtualDesktops );\n                        }\n\n                        break;\n                    }\n                }\n                else // if we drag a virtual desktop\n                {\n                    if ( _hoverVdIndex == VdIndex )\n                    {\n                        Location = _fixedPosition;\n                    }\n                    else\n                    {\n                        Swap( ConfigManager.CurrentProfile.DesktopOrder, VdIndex, _hoverVdIndex );\n\n                        VirtualDesktopManager.SaveOrder();\n\n                        Logger.Verbose( $\"SWAP.Desktop Desktop[{VdIndex.ToString()}] WITH Desktop[{_hoverVdIndex.ToString()}]\" );\n                        VirtualDesktopManager.FixLayout();\n                        VirtualDesktopManager.ShowAllVirtualDesktops();\n                        User32.PostMessage( Handle, WinMsg.WM_HOTKEY, UserMessage.RefreshVdw, 0 );\n                        User32.PostMessage( _virtualDesktops[_hoverVdIndex].Handle, WinMsg.WM_HOTKEY, UserMessage.RefreshVdw, 0 );\n                    }\n                }\n            }\n            else\n            {\n                //////////////////////////////////\n                // goes here means a Click\n                if ( _selectedWindow != null && User32.IsWindow( _selectedWindow.Handle ) ) // click on a thumbnail\n                {\n                    void ActiveWindow()\n                    {\n                        Logger.Verbose( $\"ACTIVE.Win {_selectedWindow.Title}({_selectedWindow.Handle.ToString( \"X2\" )})\" );\n                        WindowTool.ActiveWindow( _selectedWindow.Handle, ConfigManager.CurrentProfile.DesktopOrder[_hoverVdIndex] );\n                    }\n\n                    var action = Manager.Configs.GetMouseActionById( MouseAction.GetActionId( e.Button, ModifierKeys, MouseAction.MOUSE_NODE_WINDOW_PREFIX ) );\n                    switch ( action )\n                    {\n                        case MouseAction.Action.WindowActiveDesktopVisibleAndCloseView:\n                            ActiveWindow();\n                            MainWindow.HideAll();\n                            break;\n                        case MouseAction.Action.WindowActiveDesktopVisibleOnly:\n                            ActiveWindow();\n                            break;\n                        case MouseAction.Action.WindowClose:\n                            CloseSelectedWindow( _selectedWindow );\n                            break;\n                        case MouseAction.Action.ContextMenu:\n                            Menus.ThumbCtm( new MenuInfo\n                            {\n                                Vw = _selectedWindow,\n                                Sender = sender,\n                                Location = e.Location,\n                                Self = this\n                            } );\n                            break;\n                        case MouseAction.Action.WindowHideFromView:\n                            Filters.WndHandleIgnoreListByManual.TryAdd( _selectedWindow.Handle, 0 );\n                            VirtualDesktopManager.RefreshThumbs( _selectedWindow.Handle, this );\n\n                            break;\n                        case MouseAction.Action.WindowShowForSelectedProcessOnly:\n                            try\n                            {\n                                _ = User32.GetWindowThreadProcessId( _selectedWindow.Handle, out var pId );\n                                VirtualDesktopManager.ShowVisibleWindowsForDesktops( null, pId );\n                            }\n                            catch ( Exception ex )\n                            {\n                                Logger.Warning( \"show windows from selected process: \" + ex.Message );\n                            }\n\n                            break;\n                        case MouseAction.Action.WindowShowForSelectedProcessInSelectedDesktop:\n                            try\n                            {\n                                _ = User32.GetWindowThreadProcessId( _selectedWindow.Handle, out var pId );\n                                MakeTheOnlyOne( pId );\n                            }\n                            catch ( Exception ex )\n                            {\n                                Logger.Warning( \"show windows from selected process: \" + ex.Message );\n                            }\n\n                            break;\n                        case MouseAction.Action.DoNothing:\n                            break;\n                        default:\n                            ActiveWindow();\n                            MainWindow.HideAll();\n                            break;\n                    }\n                }\n                else // click on a virtual desktop\n                {\n                    var action = Manager.Configs.GetMouseActionById( MouseAction.GetActionId( e.Button, ModifierKeys, MouseAction.MOUSE_NODE_DESKTOP_PREFIX ) );\n                    switch ( action )\n                    {\n                        case MouseAction.Action.DesktopVisibleAndCloseView:\n                            MakeVisible();\n                            MainWindow.HideAll();\n                            break;\n                        case MouseAction.Action.DesktopVisibleOnly:\n                            MakeVisible();\n                            break;\n                        case MouseAction.Action.ContextMenu:\n                            Menus.VdCtm( new MenuInfo\n                                {\n                                    Sender = sender,\n                                    Location = e.Location,\n                                    Self = this,\n                                    Vdws = _virtualDesktops\n                                }\n                            );\n                            break;\n                        case MouseAction.Action.DesktopShowForSelectedDesktop:\n                            MakeTheOnlyOne();\n\n                            break;\n                        case MouseAction.Action.DoNothing:\n                            break;\n                        default:\n                            MakeVisible();\n                            MainWindow.HideAll();\n                            break;\n                    }\n                }\n            }\n\n            VirtualDesktopManager.UpdateVdwBackground();\n\n            if ( _dw != null )\n            {\n                DwmApi.DwmUnregisterThumbnail( _dw.Thumb );\n                _dw.Close();\n                _dw = null;\n            }\n\n            _dragState = 0;\n            _selectedWindow = null;\n            _dragBounds = Rectangle.Empty;\n        }\n\n        private int HoverOnDesktop( object sender, MouseEventArgs e )\n        {\n            if ( _virtualDesktops is null ) return -1;\n            _hoverVdIndex = VdIndex;\n\n            var cellIndex = MainWindow.InCell( new System.Windows.Point( Cursor.Position.X, Cursor.Position.Y ) );\n            MainWindow.UpdateHoverBorder( cellIndex );\n            foreach ( var vdw in _virtualDesktops )\n            {\n                var controlRectangle = vdw.RectangleToScreen( vdw.ClientRectangle );\n                if ( controlRectangle.Contains( Cursor.Position ) )\n                {\n                    if ( vdw.VdIndex != VdIndex )\n                    {\n                        _hoverVdIndex = vdw.VdIndex;\n                        if ( _selectedWindow != null )\n                        {\n                            if ( _dragState == 1 )\n                            {\n                                Logger.Verbose( $\"DRAGGING.Win {_selectedWindow.Title} IN Desktop[{vdw.VdIndex.ToString()}]\" );\n                                _dragState++;\n                            }\n\n                            vdw.Opacity = VirtualDesktopManager.Ui.VDWDragTargetOpacity;\n                        }\n                        else\n                        {\n                            if ( _dragState == 1 )\n                            {\n                                Logger.Verbose( $\"DRAGGING.Desk Desktop[{VdIndex.ToString()}]) ON Desktop[{vdw.VdIndex.ToString()}])\" );\n                                _dragState++;\n                            }\n                        }\n                    }\n                }\n                else\n                {\n                    vdw.Opacity = 1;\n                }\n            }\n\n            return _hoverVdIndex;\n        }\n\n        private void MakeVisible()\n        {\n            Logger.Verbose( $\"SWITCH TO DESKTOP Desktop[{_hoverVdIndex.ToString()}]\" );\n            DesktopWrapper.MakeVisibleByGuid( VdId );\n        }\n\n        private static void Swap<T>( IList<T> list, int indexA, int indexB )\n        {\n            ( list[indexA], list[indexB] ) = ( list[indexB], list[indexA] );\n        }\n\n        public async void CloseSelectedWindow( VisibleWindow vw )\n        {\n            var isWindowPinned = DesktopWrapper.IsWindowPinned( vw.Handle ) || DesktopWrapper.IsApplicationPinned( vw.Handle );\n\n            void RefreshVDs( bool isPinned )\n            {\n                if ( isPinned )\n                {\n                    VirtualDesktopManager.ShowVisibleWindowsForDesktops();\n                }\n                else\n                {\n                    VirtualDesktopManager.ShowVisibleWindowsForDesktops( new List<VirtualDesktopWindow> {this} );\n                }\n            }\n\n            // _ = User32.ShowWindow( vw.Handle, 0 );\n\n            User32.PostMessage( vw.Handle, WinMsg.WM_SYSCOMMAND, WinMsg.SC_CLOSE, 0 );\n\n            await Task.Run( () =>\n            {\n                var sw = Stopwatch.StartNew();\n                while ( sw.ElapsedMilliseconds < Const.WindowCloseTimeout )\n                {\n                    Thread.Sleep( 100 );\n                    // if ( User32.IsWindow( vw.Handle ) ) continue; // 严格的判断\n                    if ( User32.IsWindowVisible( vw.Handle ) ) continue; // 宽松的判断\n\n                    RefreshVDs( isWindowPinned );\n                    return;\n                }\n\n                RefreshVDs( isWindowPinned );\n            } ).ConfigureAwait( false );\n        }\n\n        public void MakeTheOnlyOne( int pId = 0 )\n        {\n            if ( _isTheOnlyOneInMainView )\n            {\n                MainWindow.ResetMainGrid();\n                VirtualDesktopManager.HideAllVirtualDesktops();\n                VirtualDesktopManager.ShowAllVirtualDesktops();\n                VirtualDesktopManager.ShowVisibleWindowsForDesktops();\n            }\n            else\n            {\n                MainWindow.ResetMainGridForSingleDesktop( VdIndex );\n                VirtualDesktopManager.HideAllVirtualDesktops();\n                _isTheOnlyOneInMainView = true;\n                VirtualDesktopManager.ShowAllVirtualDesktops();\n                VirtualDesktopManager.ShowVisibleWindowsForDesktops( new List<VirtualDesktopWindow> {this}, pId );\n            }\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/VirtualDesktop/VirtualDesktopWindow.Thumbs.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Windows.Forms;\nusing VirtualSpace.Helpers;\nusing ConfigManager = VirtualSpace.Config.Manager;\n\nnamespace VirtualSpace.VirtualDesktop\n{\n    public partial class VirtualDesktopWindow\n    {\n        public void AddWindow( VisibleWindow wnd )\n        {\n            _visibleWindows.Add( wnd );\n        }\n\n        public void ClearVisibleWindows()\n        {\n            ReleaseThumbnails();\n            _visibleWindows.Clear();\n        }\n\n        public void ShowThumbnails()\n        {\n            var wndCount = _visibleWindows.Count;\n            if ( !string.IsNullOrEmpty( WindowFilter.Keyword ) )\n            {\n                _visibleWindows.RemoveAll( wnd => !wnd.Title.ToLower().Contains( WindowFilter.Keyword.ToLower() ) );\n                wndCount = _visibleWindows.Count;\n            }\n\n            if ( wndCount < 1 ) return;\n            _visibleWindows.Sort( ( x, y ) => x.Title.CompareTo( y.Title ) );\n\n            var rows = Math.Floor( Math.Sqrt( wndCount ) );\n            var cols = Math.Ceiling( wndCount / rows );\n\n            var marginH = VirtualDesktopManager.Ui.ThumbMargin.Left;\n            var marginV = VirtualDesktopManager.Ui.ThumbMargin.Top;\n\n            //////////////////////////////////////\n            // thumb container size\n            var thumbWidth  = ( Width - ( cols + 1 ) * marginH ) / cols;\n            var thumbHeight = ( Height - ( rows + 1 ) * marginV ) / rows;\n\n            //////////////////////////////////////\n            // show thumbnails\n            for ( int index = 0, row = 0; row < rows; row++ )\n            {\n                var topLeftY = Padding.Top + ( row + 1 ) * marginV + row * thumbHeight;\n\n                for ( var col = 0; col < cols; col++ )\n                {\n                    if ( index >= wndCount ) break;\n                    var topLeftX = Padding.Left + ( col + 1 ) * marginH + col * thumbWidth;\n\n                    var i     = -1;\n                    var thumb = IntPtr.Zero;\n                    if ( InvokeRequired )\n                    {\n                        var idx = index;\n\n                        void Invoker()\n                        {\n                            i = DwmApi.DwmRegisterThumbnail( Handle, _visibleWindows[idx].Handle, out thumb );\n                        }\n\n                        Invoke( (MethodInvoker)Invoker );\n                    }\n                    else\n                    {\n                        i = DwmApi.DwmRegisterThumbnail( Handle, _visibleWindows[index].Handle, out thumb );\n                    }\n\n                    if ( i == 0 )\n                    {\n                        _visibleWindows[index].Thumb = thumb;\n\n                        var props = ScaleCenter(\n                            thumb,\n                            new RECT(\n                                (int)topLeftX,\n                                (int)topLeftY,\n                                (int)( topLeftX + thumbWidth ),\n                                (int)( topLeftY + thumbHeight )\n                            )\n                        );\n\n                        _visibleWindows[index].SetValidArea( props );\n                        UpdateThumbnail( thumb, props );\n                    }\n\n                    index++;\n                }\n            }\n        }\n\n        private static DWM_THUMBNAIL_PROPERTIES ScaleCenter( IntPtr thumb, RECT rect )\n        {\n            var props = new DWM_THUMBNAIL_PROPERTIES\n            {\n                fVisible = true,\n                dwFlags = DwmApi.DWM_TNP_VISIBLE | DwmApi.DWM_TNP_RECTDESTINATION | DwmApi.DWM_TNP_OPACITY,\n                opacity = 255,\n                rcDestination = rect\n            };\n\n            if ( thumb == IntPtr.Zero ) return props;\n\n            _ = DwmApi.DwmQueryThumbnailSourceSize( thumb, out var srcSize );\n\n            var cellWidth       = rect.Right - rect.Left;\n            var cellHeight      = rect.Bottom - rect.Top;\n            var cellAspectRatio = cellWidth / (double)cellHeight;\n            var srcAspectRatio  = srcSize.cx / (double)srcSize.cy;\n\n            if ( cellAspectRatio > srcAspectRatio )\n            {\n                var scaleFactor = cellHeight / (double)srcSize.cy;\n                var scaledX     = (int)( srcSize.cx * scaleFactor );\n                var xOffset     = ( cellWidth - scaledX ) / 2;\n                props.rcDestination.Left += xOffset;\n                props.rcDestination.Right -= xOffset;\n            }\n            else\n            {\n                var scaleFactor = cellWidth / (double)srcSize.cx;\n                var scaledY     = (int)( srcSize.cy * scaleFactor );\n                var yOffset     = ( cellHeight - scaledY ) / 2;\n                props.rcDestination.Top += yOffset;\n                props.rcDestination.Bottom -= yOffset;\n            }\n\n            return props;\n        }\n\n        private static void UpdateThumbnail( IntPtr thumb, DWM_THUMBNAIL_PROPERTIES props )\n        {\n            _ = DwmApi.DwmUpdateThumbnailProperties( thumb, ref props );\n        }\n\n        private void ReleaseThumbnails()\n        {\n            foreach ( var window in _visibleWindows ) _ = DwmApi.DwmUnregisterThumbnail( window.Thumb );\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/VirtualDesktop/VirtualDesktopWindow.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Collections.Generic;\nusing System.Drawing;\nusing System.Drawing.Drawing2D;\nusing System.Runtime.InteropServices;\nusing System.Threading.Tasks;\nusing System.Windows.Forms;\nusing VirtualSpace.AppLogs;\nusing VirtualSpace.Config;\nusing VirtualSpace.Helpers;\nusing VirtualSpace.VirtualDesktop.Api;\nusing ConfigManager = VirtualSpace.Config.Manager;\nusing Point = System.Drawing.Point;\nusing Size = System.Drawing.Size;\n\nnamespace VirtualSpace.VirtualDesktop\n{\n    public partial class VirtualDesktopWindow : Form\n    {\n        private static   List<VirtualDesktopWindow>? _virtualDesktops;\n        private readonly List<VisibleWindow>         _visibleWindows = new();\n        private          string                      _desktopName;\n        private          Point                       _fixedPosition;\n        private          Size                        _initSize = Size.Empty;\n        public           Guid                        VdId;\n        public           int                         VdIndex { get; set; }\n\n        private VirtualDesktopWindow()\n        {\n            InitializeComponent();\n            base.DoubleBuffered = ConfigManager.Configs.Cluster.EnableDoubleBufferedForVDW;\n        }\n\n        protected override CreateParams CreateParams\n        {\n            get\n            {\n                var cp = base.CreateParams;\n                cp.ExStyle |= 0x00000080; // WS_EX_TOOLWINDOW\n                cp.ExStyle |= 0x08000000; // WS_EX_NOACTIVATE\n                cp.Style = unchecked(cp.Style | (int)0x80000000); // WS_POPUP\n                return cp;\n            }\n        }\n\n        protected override void WndProc( ref Message m )\n        {\n            if ( m.Msg == WinMsg.WM_HOTKEY )\n            {\n                switch ( m.WParam.ToInt32() )\n                {\n                    case UserMessage.ShowVdw:\n                        ShowByVdIndex();\n                        return;\n                    case UserMessage.RefreshVdw:\n                        Refresh();\n                        return;\n                    case UserMessage.ShowThumbsOfVdw:\n                        ShowThumbnails();\n                        return;\n                }\n            }\n\n            base.WndProc( ref m );\n        }\n\n        protected override bool ShowWithoutActivation => true;\n\n        public static VirtualDesktopWindow Create( int index, Guid guid, Size initSize, Color defaultBackColor, int vdwPadding )\n        {\n            var vdw = new VirtualDesktopWindow\n            {\n                StartPosition = FormStartPosition.Manual,\n                TabStop = false,\n                TopLevel = true,\n                TopMost = true,\n                Name = \"vdw_\" + index,\n                VdId = guid,\n                VdIndex = index,\n                Size = initSize,\n                BackColor = defaultBackColor,\n                Padding = new Padding( vdwPadding ),\n                ResizeRedraw = true,\n                Text = Const.Window.VD_CONTAINER_TITLE\n            };\n            vdw.SetOwner( MainWindow.GetMainWindow() );\n            return vdw;\n        }\n\n        private void SetOwner( MainWindow owner )\n        {\n            void DoSetOwner()\n            {\n                User32.SetWindowLongPtr( new HandleRef( this, Handle ),\n                    (int)GetWindowLongFields.GWL_HWNDPARENT,\n                    owner.Handle.ToInt32()\n                );\n            }\n\n            if ( owner.Dispatcher.CheckAccess() )\n            {\n                DoSetOwner();\n            }\n            else\n            {\n                owner.Dispatcher.Invoke( DoSetOwner );\n            }\n        }\n\n        public void UpdateWallpaper()\n        {\n            if ( InvokeRequired )\n            {\n                Invoke( (MethodInvoker)Refresh );\n            }\n            else\n            {\n                Refresh();\n            }\n        }\n\n        private void VirtualDesktopWindow_Closing( object? sender, FormClosingEventArgs e )\n        {\n            e.Cancel = true;\n        }\n\n        public void RealClose()\n        {\n            FormClosing -= VirtualDesktopWindow_Closing;\n            ClearVisibleWindows();\n            Close();\n        }\n\n        private void ShowByVdIndex()\n        {\n            var ui  = VirtualDesktopManager.Ui;\n            var dpi = SysInfo.Dpi;\n\n            var matrixIndex = VirtualDesktopManager.GetMatrixIndexByVdIndex( VdIndex );\n            var location    = MainWindow.GetCellLocationByMatrixIndex( matrixIndex );\n            var point       = new Point( (int)( ( location.X + ui.VDWBorderSize ) * dpi.ScaleX ), (int)( ( location.Y + ui.VDWBorderSize ) * dpi.ScaleY ) );\n            Location = point;\n            _fixedPosition = point;\n\n            var size      = MainWindow.GetCellSizeByMatrixIndex( matrixIndex );\n            var vdwWidth  = ( size.Width - 2 * ui.VDWBorderSize ) * dpi.ScaleX + 1;\n            var vdwHeight = ( size.Height - 2 * ui.VDWBorderSize ) * dpi.ScaleY + 1;\n\n            ////////////////////////////////////////////////////////////////\n            // 虚拟桌面容器的宽/高下限，宽/高任意一个低于此值，虚拟桌面尺寸强制归零\n            if ( vdwWidth < Const.VirtualDesktop.VdwSizeFloor || vdwHeight < Const.VirtualDesktop.VdwSizeFloor )\n            {\n                Size = Size.Empty; // 强制归零，从而避免接收到鼠标事件\n            }\n            else\n            {\n                var vdName = DesktopWrapper.DesktopNameFromGuid( VdId );\n                if ( vdName != _desktopName )\n                {\n                    UpdateDesktopName( vdName );\n                }\n\n                Size = new Size( (int)vdwWidth, (int)vdwHeight );\n\n                if ( !Visible )\n                    Show();\n            }\n        }\n\n        private (bool isCached, string path, Color? color) CachedWallpaperInfo()\n        {\n            var wpPath = WinRegistry.GetWallPaperPathByGuid( VdId );\n            if ( wpPath is null )\n            {\n                return new ValueTuple<bool, string, Color>( false, \"\", WinRegistry.GetBackColor() );\n            }\n\n            var wpInfo = Wallpaper.CachedWallPaperInfo( wpPath, ConfigManager.GetCachePath(), Width, Height );\n            return new ValueTuple<bool, string, Color?>( wpInfo.Exists, wpPath, null );\n        }\n\n        private static void DrawImage( PaintEventArgs e, Wallpaper wp, int width = 0, int height = 0 )\n        {\n            if ( width > 0 && height > 0 )\n            {\n                e.Graphics.DrawImage( wp.Image, 0, 0, width, height );\n            }\n            else\n            {\n                e.Graphics.DrawImage( wp.Image, 0, 0 );\n            }\n\n            wp.Release();\n        }\n\n        private void InitPaint( (bool isCached, string path, Color? color) wpInfo, PaintEventArgs e )\n        {\n            Logger.Event( $\"Init Desktop[{VdIndex}] background.\" );\n\n            _initSize.Width = Width;\n            _initSize.Height = Height;\n\n            if ( wpInfo.color != null )\n            {\n                BackColor = (Color)wpInfo.color;\n                return;\n            }\n\n            if ( wpInfo.isCached )\n            {\n                DrawImage( e, WinRegistry.GetWallpaperByPath( wpInfo.path,\n                    Width,\n                    Height,\n                    ConfigManager.GetCachePath(),\n                    ConfigManager.Configs.Cluster.VdwWallpaperQuality ) );\n            }\n            else\n            {\n                if ( VirtualDesktopManager.IsBatchCreate )\n                {\n                    DrawImage( e, WinRegistry.GetWallpaperByPath( wpInfo.path,\n                        Width,\n                        Height,\n                        ConfigManager.GetCachePath(),\n                        ConfigManager.Configs.Cluster.VdwWallpaperQuality ) );\n                }\n                else\n                {\n                    var hWnd = Handle;\n                    Task.Run( () =>\n                    {\n                        WinRegistry.GetWallpaperByPath( wpInfo.path,\n                            Width,\n                            Height,\n                            ConfigManager.GetCachePath(),\n                            ConfigManager.Configs.Cluster.VdwWallpaperQuality ).Release();\n                        User32.PostMessage( hWnd, WinMsg.WM_HOTKEY, UserMessage.RefreshVdw, 0 );\n                    } );\n                }\n            }\n        }\n\n        private void NormalPaint( (bool isCached, string path, Color? color) wpInfo, PaintEventArgs e )\n        {\n            if ( wpInfo.color != null )\n            {\n                BackColor = (Color)wpInfo.color;\n                return;\n            }\n\n            if ( wpInfo.isCached )\n            {\n                DrawImage( e, WinRegistry.GetWallpaperByPath( wpInfo.path,\n                    Width,\n                    Height,\n                    ConfigManager.GetCachePath(),\n                    ConfigManager.Configs.Cluster.VdwWallpaperQuality ) );\n            }\n            else\n            {\n                Logger.Event( $\"Create cache image({Width}*{Height}) for Desktop[{VdIndex}]\" );\n                Task.Run( () =>\n                {\n                    // only once for path with current Width*Height\n                    WinRegistry.GetWallpaperByPath( wpInfo.path,\n                            Width,\n                            Height,\n                            ConfigManager.GetCachePath(),\n                            ConfigManager.Configs.Cluster.VdwWallpaperQuality )\n                        .Release();\n                } );\n\n                ////////////////////////////////////////////////////////////////////////////////////\n                // use init size, so we can create cache image async\n                e.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor; // faster\n                DrawImage( e, WinRegistry.GetWallpaperByPath( wpInfo.path,\n                    _initSize.Width,\n                    _initSize.Height,\n                    ConfigManager.GetCachePath(),\n                    ConfigManager.Configs.Cluster.VdwWallpaperQuality ), Width, Height );\n            }\n        }\n\n        private void RefreshThumbs( object? o, EventArgs e )\n        {\n            Logger.Event( $\"Repaint thumbs in Desktop[{VdIndex}] due to size changed.\" );\n            ReleaseThumbnails();\n            ShowThumbnails();\n        }\n\n        private void pbWallpaper_Paint( object sender, PaintEventArgs e )\n        {\n            var wpInfo = CachedWallpaperInfo();\n            if ( _initSize == Size.Empty )\n            {\n                Resize += RefreshThumbs;\n                InitPaint( wpInfo, e );\n            }\n            else\n            {\n                NormalPaint( wpInfo, e );\n            }\n\n            var ui  = ConfigManager.CurrentProfile.UI;\n            var str = \"\";\n\n            if ( ui.ShowVdName )\n            {\n                str += _desktopName;\n            }\n\n            if ( ui.ShowVdIndex )\n            {\n                str += ui.ShowVdIndexType == 0 ? $\"[{VdIndex}]\" : $\"[{VdIndex + 1}]\";\n            }\n\n            if ( str == \"\" ) return;\n\n            using var font = new Font( \"Segoe UI emoji\", 10 );\n            e.Graphics.DrawString(\n                str,\n                font,\n                Brushes.Beige,\n                new Point( 2, Height - 30 )\n            );\n        }\n\n        public void UpdateDesktopName( string name )\n        {\n            _desktopName = name;\n            Refresh();\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/VirtualDesktop/VirtualDesktopWindow.resx",
    "content": "﻿<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n</root>"
  },
  {
    "path": "VirtualSpace/VirtualDesktop/VisibleWindow.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Drawing;\nusing VirtualSpace.Helpers;\n\nnamespace VirtualSpace.VirtualDesktop\n{\n    public class VisibleWindow\n    {\n        public VisibleWindow( string title, string classname, IntPtr handle )\n        {\n            Title = title;\n            Classname = classname;\n            Handle = handle;\n        }\n\n        public string Title { get; set; }\n\n        public string Classname { get; set; }\n\n        public IntPtr Handle { get; set; }\n\n        public Rectangle Rect { get; set; }\n\n        public IntPtr Thumb { get; set; }\n\n        internal DWM_THUMBNAIL_PROPERTIES DTP { get; set; }\n\n        internal void SetValidArea( DWM_THUMBNAIL_PROPERTIES props )\n        {\n            DTP = props;\n            Rect = new Rectangle\n            {\n                X = props.rcDestination.Left,\n                Y = props.rcDestination.Top,\n                Width = props.rcDestination.Right - props.rcDestination.Left,\n                Height = props.rcDestination.Bottom - props.rcDestination.Top\n            };\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/VirtualSpace.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <OutputType>WinExe</OutputType>\n        <TargetFrameworks>net6.0-windows</TargetFrameworks>\n        <Nullable>enable</Nullable>\n        <UseWPF>true</UseWPF>\n        <StartupObject>VirtualSpace.Program</StartupObject>\n        <UseWindowsForms>True</UseWindowsForms>\n        <ApplicationIcon>Resources\\Logo_2.ico</ApplicationIcon>\n        <ApplicationManifest>app.manifest</ApplicationManifest>\n        <Platforms>AnyCPU;x64;x86</Platforms>\n        <LangVersion>9</LangVersion>\n        <CsWinRTEnabled>false</CsWinRTEnabled>\n    </PropertyGroup>\n\n    <PropertyGroup>\n        <GenerateAssemblyInfo>false</GenerateAssemblyInfo>\n        <OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles>\n    </PropertyGroup>\n\n    <Target Name=\"TextTemplateTransform\" BeforeTargets=\"BeforeBuild\" Condition=\"'$(Configuration)'=='Release'\">\n        <Message Text=\"======TextTemplateTransform begin======\" Importance=\"High\"/>\n        <Exec WorkingDirectory=\"$(ProjectDir)\" Command=\"&quot;$(DevEnvDir)TextTransform.exe&quot; -out &quot;$(ProjectDir)AutoVersion.cs&quot; &quot;$(ProjectDir)AutoVersion.tt&quot;\">\n            <Output TaskParameter=\"ConsoleOutput\" PropertyName=\"OutputOfExec\"/>\n        </Exec>\n        <Message Text=\"======TextTemplateTransform end======\" Importance=\"High\"/>\n    </Target>\n\n    <ItemGroup>\n        <ApplicationDefinition Remove=\"App.xaml\"/>\n        <Page Include=\"App.xaml\"/>\n    </ItemGroup>\n\n    <ItemGroup>\n        <Compile Update=\"AutoVersion.cs\">\n            <DesignTime>True</DesignTime>\n            <DependentUpon>AutoVersion.tt</DependentUpon>\n        </Compile>\n    </ItemGroup>\n\n    <PropertyGroup Condition=\"'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net6.0-windows|AnyCPU'\">\n        <NoWarn>1701;1702;CA1416;CS8618</NoWarn>\n    </PropertyGroup>\n\n    <PropertyGroup Condition=\"'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net6.0-windows|AnyCPU'\">\n        <NoWarn>1701;1702;CA1416;CS8618</NoWarn>\n    </PropertyGroup>\n\n    <PropertyGroup Condition=\"'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net6.0-windows|x64'\">\n        <NoWarn>1701;1702;CA1416;CS8618</NoWarn>\n    </PropertyGroup>\n\n    <PropertyGroup Condition=\"'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net6.0-windows|x64'\">\n        <NoWarn>1701;1702;CA1416;CS8618</NoWarn>\n    </PropertyGroup>\n\n    <PropertyGroup Condition=\"'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net6.0-windows|x86'\">\n        <NoWarn>1701;1702;CA1416;CS8618</NoWarn>\n    </PropertyGroup>\n\n    <PropertyGroup Condition=\"'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net6.0-windows|x86'\">\n        <NoWarn>1701;1702;CA1416;CS8618</NoWarn>\n    </PropertyGroup>\n\n    <ItemGroup>\n        <Content Include=\"Resources\\Logo_2.ico\"/>\n    </ItemGroup>\n\n    <ItemGroup>\n        <EmbeddedResource Include=\"..\\VirtualDesktop\\VirtualDesktop10\\bin\\Release\\net6.0-windows\\VirtualDesktop10.dll\" Link=\"Resources\\VirtualDesktop10.dll\"/>\n        <EmbeddedResource Include=\"..\\VirtualDesktop\\VirtualDesktop11\\bin\\Release\\net6.0-windows\\VirtualDesktop11.dll\" Link=\"Resources\\VirtualDesktop11.dll\"/>\n        <EmbeddedResource Include=\"..\\VirtualDesktop\\VirtualDesktop11_21H2\\bin\\Release\\net6.0-windows\\VirtualDesktop11_21H2.dll\" Link=\"Resources\\VirtualDesktop11_21H2.dll\"/>\n        <EmbeddedResource Include=\"..\\VirtualDesktop\\VirtualDesktop11_23H2\\bin\\Release\\net6.0-windows\\VirtualDesktop11_23H2.dll\" Link=\"Resources\\VirtualDesktop11_23H2.dll\"/>\n        <EmbeddedResource Include=\"..\\VirtualDesktop\\VirtualDesktop11_23H2_3085\\bin\\Release\\net6.0-windows\\VirtualDesktop11_23H2_3085.dll\" Link=\"Resources\\VirtualDesktop11_23H2_3085.dll\"/>\n        <EmbeddedResource Include=\"..\\VirtualDesktop\\VirtualDesktop11_24H2\\bin\\Release\\net6.0-windows\\VirtualDesktop11_24H2.dll\" Link=\"Resources\\VirtualDesktop11_24H2.dll\"/>\n    </ItemGroup>\n\n    <ItemGroup>\n        <ProjectReference Include=\"..\\VirtualDesktop\\VirtualDesktop10\\VirtualDesktop10.csproj\">\n            <Aliases>VirtualDesktop10</Aliases>\n            <ExcludeFromSingleFile>true</ExcludeFromSingleFile>\n        </ProjectReference>\n        <ProjectReference Include=\"..\\VirtualDesktop\\VirtualDesktop11\\VirtualDesktop11.csproj\">\n            <Aliases>VirtualDesktop11</Aliases>\n            <ExcludeFromSingleFile>true</ExcludeFromSingleFile>\n        </ProjectReference>\n        <ProjectReference Include=\"..\\VirtualDesktop\\VirtualDesktop11_21H2\\VirtualDesktop11_21H2.csproj\">\n            <Aliases>VirtualDesktop11_21H2</Aliases>\n            <ExcludeFromSingleFile>true</ExcludeFromSingleFile>\n        </ProjectReference>\n        <ProjectReference Include=\"..\\VirtualDesktop\\VirtualDesktop11_23H2\\VirtualDesktop11_23H2.csproj\">\n            <Aliases>VirtualDesktop11_23H2</Aliases>\n            <ExcludeFromSingleFile>true</ExcludeFromSingleFile>\n        </ProjectReference>\n        <ProjectReference Include=\"..\\VirtualDesktop\\VirtualDesktop11_23H2_3085\\VirtualDesktop11_23H2_3085.csproj\">\n            <Aliases>VirtualDesktop11_23H2_3085</Aliases>\n            <ExcludeFromSingleFile>true</ExcludeFromSingleFile>\n        </ProjectReference>\n        <ProjectReference Include=\"..\\VirtualDesktop\\VirtualDesktop11_24H2\\VirtualDesktop11_24H2.csproj\">\n            <Aliases>VirtualDesktop11_24H2</Aliases>\n            <ExcludeFromSingleFile>true</ExcludeFromSingleFile>\n        </ProjectReference>\n    </ItemGroup>\n\n    <ItemGroup>\n        <ProjectReference Include=\"..\\WPF\\ControlPanel\\ControlPanel.csproj\"/>\n    </ItemGroup>\n\n    <Target Name=\"DeletePdb\" AfterTargets=\"Publish\">\n        <ItemGroup>\n            <FileToDelete Include=\"bin\\**\\*.pdb\"/>\n        </ItemGroup>\n        <Delete Files=\"@(FileToDelete)\"/>\n        <Message Text=\"Deleted files: '@(FileToDelete)'\" Importance=\"high\"/>\n    </Target>\n\n    <PropertyGroup>\n        <SatelliteResourceLanguages>en-US,zh-Hans</SatelliteResourceLanguages>\n    </PropertyGroup>\n\n</Project>\n"
  },
  {
    "path": "VirtualSpace/WindowFilter.xaml",
    "content": "﻿<Window x:Class=\"VirtualSpace.WindowFilter\"\n        xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n        xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n        xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n        xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n        mc:Ignorable=\"d\" AllowsTransparency=\"True\" Background=\"Transparent\"\n        Height=\"100\" Width=\"800\" Topmost=\"True\" ShowInTaskbar=\"False\" WindowStyle=\"None\" ResizeMode=\"NoResize\">\n    <Grid Margin=\"10,5,10,10\">\n        <TextBox x:Name=\"tbFilter\" ContextMenu=\"{x:Null}\" BorderThickness=\"0\"\n                 FontSize=\"50\" Background=\"Black\" Foreground=\"Beige\" Padding=\"10,0\">\n        </TextBox>\n    </Grid>\n</Window>"
  },
  {
    "path": "VirtualSpace/WindowFilter.xaml.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Runtime.InteropServices;\nusing System.Timers;\nusing System.Windows;\nusing System.Windows.Interop;\nusing VirtualSpace.Config;\nusing VirtualSpace.Helpers;\nusing VirtualSpace.VirtualDesktop;\n\nnamespace VirtualSpace\n{\n    public partial class WindowFilter : Window\n    {\n        private static WindowFilter? _instance;\n        private static IntPtr        _handle;\n        private static string        _lastKeyword = string.Empty;\n\n        private static readonly Timer FilterTimer = new()\n        {\n            Enabled = true,\n            Interval = Manager.Configs.Cluster.WindowFilterKeywordScanningInterval\n        };\n\n        private WindowFilter()\n        {\n            InitializeComponent();\n        }\n\n        public static WindowFilter GetInstance( IntPtr handle )\n        {\n            if ( _instance == null )\n            {\n                _instance = new WindowFilter\n                {\n                    Height = Const.Window.WINDOW_FILTER_BAR_HEIGHT,\n                    Title = Const.Window.VS_WINDOW_FILTER_TITLE\n                };\n                new WindowInteropHelper( _instance ).EnsureHandle();\n            }\n\n            User32.SetWindowLongPtr( new HandleRef( _instance, _handle ),\n                (int)GetWindowLongFields.GWL_HWNDPARENT,\n                handle.ToInt32()\n            );\n\n            FilterTimer.Elapsed += FilterTimerOnElapsed;\n\n            return _instance;\n        }\n\n        private static void FilterTimerOnElapsed( object? sender, ElapsedEventArgs e )\n        {\n            if ( _lastKeyword == Keyword ) return;\n            _lastKeyword = Keyword;\n            VirtualDesktopManager.ShowVisibleWindowsForDesktops();\n        }\n\n        protected override void OnSourceInitialized( EventArgs e )\n        {\n            base.OnSourceInitialized( e );\n            _handle = new WindowInteropHelper( this ).EnsureHandle();\n        }\n\n        public void SetFocus()\n        {\n            User32.SetForegroundWindow( _handle );\n            tbFilter.Focus();\n\n            FilterTimer.Start();\n        }\n\n        public void ClearAndHide( bool clearKeyword = true )\n        {\n            FilterTimer.Stop();\n            if ( clearKeyword )\n            {\n                _lastKeyword = string.Empty;\n                tbFilter.Clear();\n            }\n\n            if ( clearKeyword )\n            {\n                Close();\n                _instance = null;\n            }\n            else\n            {\n                Hide();\n            }\n        }\n\n        public static string Keyword\n        {\n            get\n            {\n                if ( _instance == null ) return string.Empty;\n                if ( _instance.tbFilter.CheckAccess() )\n                {\n                    return _instance.tbFilter.Text;\n                }\n\n                return _instance.Dispatcher.Invoke( () => _instance.tbFilter.Text );\n            }\n        }\n    }\n}"
  },
  {
    "path": "VirtualSpace/app.manifest",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<assembly manifestVersion=\"1.0\" xmlns=\"urn:schemas-microsoft-com:asm.v1\">\n    <assemblyIdentity version=\"1.0.0.0\" name=\"VirtualSpace\"/>\n    <trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v2\">\n        <security>\n            <requestedPrivileges xmlns=\"urn:schemas-microsoft-com:asm.v3\">\n                <!-- UAC 清单选项\n                     如果想要更改 Windows 用户帐户控制级别，请使用\n                     以下节点之一替换 requestedExecutionLevel 节点。n\n                <requestedExecutionLevel  level=\"asInvoker\" uiAccess=\"false\" />\n                <requestedExecutionLevel  level=\"requireAdministrator\" uiAccess=\"false\" />\n                <requestedExecutionLevel  level=\"highestAvailable\" uiAccess=\"false\" />\n        \n                    指定 requestedExecutionLevel 元素将禁用文件和注册表虚拟化。\n                    如果你的应用程序需要此虚拟化来实现向后兼容性，则删除此\n                    元素。\n                -->\n                <requestedExecutionLevel level=\"asInvoker\" uiAccess=\"false\"/>\n            </requestedPrivileges>\n        </security>\n    </trustInfo>\n\n    <compatibility xmlns=\"urn:schemas-microsoft-com:compatibility.v1\">\n        <application>\n            <!-- 设计此应用程序与其一起工作且已针对此应用程序进行测试的\n                 Windows 版本的列表。取消评论适当的元素，\n                 Windows 将自动选择最兼容的环境。 -->\n\n            <!-- Windows Vista -->\n            <!--<supportedOS Id=\"{e2011457-1546-43c5-a5fe-008deee3d3f0}\" />-->\n\n            <!-- Windows 7 -->\n            <!--<supportedOS Id=\"{35138b9a-5d96-4fbd-8e2d-a2440225f93a}\" />-->\n\n            <!-- Windows 8 -->\n            <!--<supportedOS Id=\"{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}\" />-->\n\n            <!-- Windows 8.1 -->\n            <!--<supportedOS Id=\"{1f676c76-80e1-4239-95bb-83d0f6d0da78}\" />-->\n\n            <!-- Windows 10 -->\n            <supportedOS Id=\"{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}\"/>\n\n        </application>\n    </compatibility>\n\n    <!-- 指示该应用程序可感知 DPI 且 Windows 在 DPI 较高时将不会对其进行\n         自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI，无需\n         选择加入。选择加入此设置的 Windows 窗体应用程序(面向 .NET Framework 4.6)还应\n         在其 app.config 中将 \"EnableWindowsFormsHighDpiAutoResizing\" 设置设置为 \"true\"。\n         \n         将应用程序设为感知长路径。请参阅 https://docs.microsoft.com/windows/win32/fileio/maximum-file-path-limitation -->\n    <!--\n    <application xmlns=\"urn:schemas-microsoft-com:asm.v3\">\n      <windowsSettings>\n        <dpiAware xmlns=\"http://schemas.microsoft.com/SMI/2005/WindowsSettings\">true</dpiAware>\n        <longPathAware xmlns=\"http://schemas.microsoft.com/SMI/2016/WindowsSettings\">true</longPathAware>\n      </windowsSettings>\n    </application>\n    -->\n\n    <!-- 启用 Windows 公共控件和对话框的主题(Windows XP 和更高版本) -->\n    <!--\n    <dependency>\n      <dependentAssembly>\n        <assemblyIdentity\n            type=\"win32\"\n            name=\"Microsoft.Windows.Common-Controls\"\n            version=\"6.0.0.0\"\n            processorArchitecture=\"*\"\n            publicKeyToken=\"6595b64144ccf1df\"\n            language=\"*\"\n          />\n      </dependentAssembly>\n    </dependency>\n    -->\n\n</assembly>\n"
  },
  {
    "path": "VirtualSpace.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 17\nVisualStudioVersion = 17.0.31919.166\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"VirtualSpace\", \"VirtualSpace\\VirtualSpace.csproj\", \"{DB52639D-5D7C-48D6-A4E1-0287C0323F6D}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"LinqExpressionBuilder\", \"LinqExpressionBuilder\\LinqExpressionBuilder.csproj\", \"{39DADF49-9596-420D-8663-4F44F3A3179D}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Configuration\", \"Configuration\\Configuration.csproj\", \"{1BC48019-B0BC-434E-8677-B720DA769365}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Logger\", \"Logger\\Logger.csproj\", \"{FF6514E2-0F29-4694-AA57-DA539144DE56}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Helpers\", \"Helpers\\Helpers.csproj\", \"{C585EA4E-FB09-47E9-B860-CE551701C25B}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Bridge\", \"Bridge\\Bridge.csproj\", \"{307A5E39-85D4-42C3-B267-B36706BB1F86}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Ipc\", \"Ipc\\Commons\\Ipc.csproj\", \"{24AC7B65-7A18-4603-AB5A-B50A6903E5BF}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"IpcServer\", \"Ipc\\IpcServer\\IpcServer.csproj\", \"{B7B5F165-21C3-456B-8F13-4C72FF6E6D32}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Plugin\", \"Plugin\\Commons\\Plugin.csproj\", \"{36332EB5-80A3-4B90-998A-55D24AB17715}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"AppController\", \"WinForms\\AppController\\AppController.csproj\", \"{0C239946-4CA8-44B0-B0A3-7785931FAEB9}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"PluginHost\", \"Plugin\\PluginHost\\PluginHost.csproj\", \"{8789C787-2125-413E-BB38-C9065C405D42}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"VirtualDesktop10\", \"VirtualDesktop\\VirtualDesktop10\\VirtualDesktop10.csproj\", \"{B4CFADA1-1DC9-4E84-AE6C-64519D5FEB19}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"VirtualDesktop11\", \"VirtualDesktop\\VirtualDesktop11\\VirtualDesktop11.csproj\", \"{E497EEBC-3B5C-4169-9DFA-37FEBBB7797A}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"VirtualDesktop11_21H2\", \"VirtualDesktop\\VirtualDesktop11_21H2\\VirtualDesktop11_21H2.csproj\", \"{F63B2561-6C6C-4010-A63A-AAB03F8C3E30}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"VirtualDesktopWrapper\", \"VirtualDesktopWrapper\\VirtualDesktopWrapper.csproj\", \"{1E662F33-8F91-48EB-A659-594E7039C65A}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"ControlPanel\", \"WPF\\ControlPanel\\ControlPanel.csproj\", \"{FAC71622-8310-4139-944B-F1FBF6588843}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"VirtualDesktop11_23H2\", \"VirtualDesktop\\VirtualDesktop11_23H2\\VirtualDesktop11_23H2.csproj\", \"{8D57B4D2-AB2E-41D4-AE7D-D6A4A173A40F}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"VirtualDesktop11_23H2_3085\", \"VirtualDesktop\\VirtualDesktop11_23H2_3085\\VirtualDesktop11_23H2_3085.csproj\", \"{698A0646-07E5-4A43-8D02-229BF3571086}\"\nEndProject\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"VirtualDesktop11_24H2\", \"VirtualDesktop\\VirtualDesktop11_24H2\\VirtualDesktop11_24H2.csproj\", \"{D51F509E-9970-4454-B246-0970FF6C69CC}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tDebug|x64 = Debug|x64\n\t\tDebug|x86 = Debug|x86\n\t\tRelease|Any CPU = Release|Any CPU\n\t\tRelease|x64 = Release|x64\n\t\tRelease|x86 = Release|x86\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{DB52639D-5D7C-48D6-A4E1-0287C0323F6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{DB52639D-5D7C-48D6-A4E1-0287C0323F6D}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{DB52639D-5D7C-48D6-A4E1-0287C0323F6D}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{DB52639D-5D7C-48D6-A4E1-0287C0323F6D}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{DB52639D-5D7C-48D6-A4E1-0287C0323F6D}.Debug|x86.ActiveCfg = Debug|x86\n\t\t{DB52639D-5D7C-48D6-A4E1-0287C0323F6D}.Debug|x86.Build.0 = Debug|x86\n\t\t{DB52639D-5D7C-48D6-A4E1-0287C0323F6D}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{DB52639D-5D7C-48D6-A4E1-0287C0323F6D}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{DB52639D-5D7C-48D6-A4E1-0287C0323F6D}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{DB52639D-5D7C-48D6-A4E1-0287C0323F6D}.Release|x64.Build.0 = Release|Any CPU\n\t\t{DB52639D-5D7C-48D6-A4E1-0287C0323F6D}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{DB52639D-5D7C-48D6-A4E1-0287C0323F6D}.Release|x86.Build.0 = Release|Any CPU\n\t\t{39DADF49-9596-420D-8663-4F44F3A3179D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{39DADF49-9596-420D-8663-4F44F3A3179D}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{39DADF49-9596-420D-8663-4F44F3A3179D}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{39DADF49-9596-420D-8663-4F44F3A3179D}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{39DADF49-9596-420D-8663-4F44F3A3179D}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{39DADF49-9596-420D-8663-4F44F3A3179D}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{39DADF49-9596-420D-8663-4F44F3A3179D}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{39DADF49-9596-420D-8663-4F44F3A3179D}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{39DADF49-9596-420D-8663-4F44F3A3179D}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{39DADF49-9596-420D-8663-4F44F3A3179D}.Release|x64.Build.0 = Release|Any CPU\n\t\t{39DADF49-9596-420D-8663-4F44F3A3179D}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{39DADF49-9596-420D-8663-4F44F3A3179D}.Release|x86.Build.0 = Release|Any CPU\n\t\t{1BC48019-B0BC-434E-8677-B720DA769365}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{1BC48019-B0BC-434E-8677-B720DA769365}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{1BC48019-B0BC-434E-8677-B720DA769365}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{1BC48019-B0BC-434E-8677-B720DA769365}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{1BC48019-B0BC-434E-8677-B720DA769365}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{1BC48019-B0BC-434E-8677-B720DA769365}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{1BC48019-B0BC-434E-8677-B720DA769365}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{1BC48019-B0BC-434E-8677-B720DA769365}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{1BC48019-B0BC-434E-8677-B720DA769365}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{1BC48019-B0BC-434E-8677-B720DA769365}.Release|x64.Build.0 = Release|Any CPU\n\t\t{1BC48019-B0BC-434E-8677-B720DA769365}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{1BC48019-B0BC-434E-8677-B720DA769365}.Release|x86.Build.0 = Release|Any CPU\n\t\t{FF6514E2-0F29-4694-AA57-DA539144DE56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{FF6514E2-0F29-4694-AA57-DA539144DE56}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{FF6514E2-0F29-4694-AA57-DA539144DE56}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{FF6514E2-0F29-4694-AA57-DA539144DE56}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{FF6514E2-0F29-4694-AA57-DA539144DE56}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{FF6514E2-0F29-4694-AA57-DA539144DE56}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{FF6514E2-0F29-4694-AA57-DA539144DE56}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{FF6514E2-0F29-4694-AA57-DA539144DE56}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{FF6514E2-0F29-4694-AA57-DA539144DE56}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{FF6514E2-0F29-4694-AA57-DA539144DE56}.Release|x64.Build.0 = Release|Any CPU\n\t\t{FF6514E2-0F29-4694-AA57-DA539144DE56}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{FF6514E2-0F29-4694-AA57-DA539144DE56}.Release|x86.Build.0 = Release|Any CPU\n\t\t{C585EA4E-FB09-47E9-B860-CE551701C25B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{C585EA4E-FB09-47E9-B860-CE551701C25B}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{C585EA4E-FB09-47E9-B860-CE551701C25B}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{C585EA4E-FB09-47E9-B860-CE551701C25B}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{C585EA4E-FB09-47E9-B860-CE551701C25B}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{C585EA4E-FB09-47E9-B860-CE551701C25B}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{C585EA4E-FB09-47E9-B860-CE551701C25B}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{C585EA4E-FB09-47E9-B860-CE551701C25B}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{C585EA4E-FB09-47E9-B860-CE551701C25B}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{C585EA4E-FB09-47E9-B860-CE551701C25B}.Release|x64.Build.0 = Release|Any CPU\n\t\t{C585EA4E-FB09-47E9-B860-CE551701C25B}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{C585EA4E-FB09-47E9-B860-CE551701C25B}.Release|x86.Build.0 = Release|Any CPU\n\t\t{307A5E39-85D4-42C3-B267-B36706BB1F86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{307A5E39-85D4-42C3-B267-B36706BB1F86}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{307A5E39-85D4-42C3-B267-B36706BB1F86}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{307A5E39-85D4-42C3-B267-B36706BB1F86}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{307A5E39-85D4-42C3-B267-B36706BB1F86}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{307A5E39-85D4-42C3-B267-B36706BB1F86}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{307A5E39-85D4-42C3-B267-B36706BB1F86}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{307A5E39-85D4-42C3-B267-B36706BB1F86}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{307A5E39-85D4-42C3-B267-B36706BB1F86}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{307A5E39-85D4-42C3-B267-B36706BB1F86}.Release|x64.Build.0 = Release|Any CPU\n\t\t{307A5E39-85D4-42C3-B267-B36706BB1F86}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{307A5E39-85D4-42C3-B267-B36706BB1F86}.Release|x86.Build.0 = Release|Any CPU\n\t\t{24AC7B65-7A18-4603-AB5A-B50A6903E5BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{24AC7B65-7A18-4603-AB5A-B50A6903E5BF}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{24AC7B65-7A18-4603-AB5A-B50A6903E5BF}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{24AC7B65-7A18-4603-AB5A-B50A6903E5BF}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{24AC7B65-7A18-4603-AB5A-B50A6903E5BF}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{24AC7B65-7A18-4603-AB5A-B50A6903E5BF}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{24AC7B65-7A18-4603-AB5A-B50A6903E5BF}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{24AC7B65-7A18-4603-AB5A-B50A6903E5BF}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{24AC7B65-7A18-4603-AB5A-B50A6903E5BF}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{24AC7B65-7A18-4603-AB5A-B50A6903E5BF}.Release|x64.Build.0 = Release|Any CPU\n\t\t{24AC7B65-7A18-4603-AB5A-B50A6903E5BF}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{24AC7B65-7A18-4603-AB5A-B50A6903E5BF}.Release|x86.Build.0 = Release|Any CPU\n\t\t{B7B5F165-21C3-456B-8F13-4C72FF6E6D32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{B7B5F165-21C3-456B-8F13-4C72FF6E6D32}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{B7B5F165-21C3-456B-8F13-4C72FF6E6D32}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{B7B5F165-21C3-456B-8F13-4C72FF6E6D32}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{B7B5F165-21C3-456B-8F13-4C72FF6E6D32}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{B7B5F165-21C3-456B-8F13-4C72FF6E6D32}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{B7B5F165-21C3-456B-8F13-4C72FF6E6D32}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{B7B5F165-21C3-456B-8F13-4C72FF6E6D32}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{B7B5F165-21C3-456B-8F13-4C72FF6E6D32}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{B7B5F165-21C3-456B-8F13-4C72FF6E6D32}.Release|x64.Build.0 = Release|Any CPU\n\t\t{B7B5F165-21C3-456B-8F13-4C72FF6E6D32}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{B7B5F165-21C3-456B-8F13-4C72FF6E6D32}.Release|x86.Build.0 = Release|Any CPU\n\t\t{36332EB5-80A3-4B90-998A-55D24AB17715}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{36332EB5-80A3-4B90-998A-55D24AB17715}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{36332EB5-80A3-4B90-998A-55D24AB17715}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{36332EB5-80A3-4B90-998A-55D24AB17715}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{36332EB5-80A3-4B90-998A-55D24AB17715}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{36332EB5-80A3-4B90-998A-55D24AB17715}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{36332EB5-80A3-4B90-998A-55D24AB17715}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{36332EB5-80A3-4B90-998A-55D24AB17715}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{36332EB5-80A3-4B90-998A-55D24AB17715}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{36332EB5-80A3-4B90-998A-55D24AB17715}.Release|x64.Build.0 = Release|Any CPU\n\t\t{36332EB5-80A3-4B90-998A-55D24AB17715}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{36332EB5-80A3-4B90-998A-55D24AB17715}.Release|x86.Build.0 = Release|Any CPU\n\t\t{0C239946-4CA8-44B0-B0A3-7785931FAEB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{0C239946-4CA8-44B0-B0A3-7785931FAEB9}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{0C239946-4CA8-44B0-B0A3-7785931FAEB9}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{0C239946-4CA8-44B0-B0A3-7785931FAEB9}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{0C239946-4CA8-44B0-B0A3-7785931FAEB9}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{0C239946-4CA8-44B0-B0A3-7785931FAEB9}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{0C239946-4CA8-44B0-B0A3-7785931FAEB9}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{0C239946-4CA8-44B0-B0A3-7785931FAEB9}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{0C239946-4CA8-44B0-B0A3-7785931FAEB9}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{0C239946-4CA8-44B0-B0A3-7785931FAEB9}.Release|x64.Build.0 = Release|Any CPU\n\t\t{0C239946-4CA8-44B0-B0A3-7785931FAEB9}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{0C239946-4CA8-44B0-B0A3-7785931FAEB9}.Release|x86.Build.0 = Release|Any CPU\n\t\t{8789C787-2125-413E-BB38-C9065C405D42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{8789C787-2125-413E-BB38-C9065C405D42}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{8789C787-2125-413E-BB38-C9065C405D42}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{8789C787-2125-413E-BB38-C9065C405D42}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{8789C787-2125-413E-BB38-C9065C405D42}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{8789C787-2125-413E-BB38-C9065C405D42}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{8789C787-2125-413E-BB38-C9065C405D42}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{8789C787-2125-413E-BB38-C9065C405D42}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{8789C787-2125-413E-BB38-C9065C405D42}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{8789C787-2125-413E-BB38-C9065C405D42}.Release|x64.Build.0 = Release|Any CPU\n\t\t{8789C787-2125-413E-BB38-C9065C405D42}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{8789C787-2125-413E-BB38-C9065C405D42}.Release|x86.Build.0 = Release|Any CPU\n\t\t{B4CFADA1-1DC9-4E84-AE6C-64519D5FEB19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{B4CFADA1-1DC9-4E84-AE6C-64519D5FEB19}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{B4CFADA1-1DC9-4E84-AE6C-64519D5FEB19}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{B4CFADA1-1DC9-4E84-AE6C-64519D5FEB19}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{B4CFADA1-1DC9-4E84-AE6C-64519D5FEB19}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{B4CFADA1-1DC9-4E84-AE6C-64519D5FEB19}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{B4CFADA1-1DC9-4E84-AE6C-64519D5FEB19}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{B4CFADA1-1DC9-4E84-AE6C-64519D5FEB19}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{B4CFADA1-1DC9-4E84-AE6C-64519D5FEB19}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{B4CFADA1-1DC9-4E84-AE6C-64519D5FEB19}.Release|x64.Build.0 = Release|Any CPU\n\t\t{B4CFADA1-1DC9-4E84-AE6C-64519D5FEB19}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{B4CFADA1-1DC9-4E84-AE6C-64519D5FEB19}.Release|x86.Build.0 = Release|Any CPU\n\t\t{E497EEBC-3B5C-4169-9DFA-37FEBBB7797A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{E497EEBC-3B5C-4169-9DFA-37FEBBB7797A}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{E497EEBC-3B5C-4169-9DFA-37FEBBB7797A}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{E497EEBC-3B5C-4169-9DFA-37FEBBB7797A}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{E497EEBC-3B5C-4169-9DFA-37FEBBB7797A}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{E497EEBC-3B5C-4169-9DFA-37FEBBB7797A}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{E497EEBC-3B5C-4169-9DFA-37FEBBB7797A}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{E497EEBC-3B5C-4169-9DFA-37FEBBB7797A}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{E497EEBC-3B5C-4169-9DFA-37FEBBB7797A}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{E497EEBC-3B5C-4169-9DFA-37FEBBB7797A}.Release|x64.Build.0 = Release|Any CPU\n\t\t{E497EEBC-3B5C-4169-9DFA-37FEBBB7797A}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{E497EEBC-3B5C-4169-9DFA-37FEBBB7797A}.Release|x86.Build.0 = Release|Any CPU\n\t\t{F63B2561-6C6C-4010-A63A-AAB03F8C3E30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{F63B2561-6C6C-4010-A63A-AAB03F8C3E30}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{F63B2561-6C6C-4010-A63A-AAB03F8C3E30}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{F63B2561-6C6C-4010-A63A-AAB03F8C3E30}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{F63B2561-6C6C-4010-A63A-AAB03F8C3E30}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{F63B2561-6C6C-4010-A63A-AAB03F8C3E30}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{F63B2561-6C6C-4010-A63A-AAB03F8C3E30}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{F63B2561-6C6C-4010-A63A-AAB03F8C3E30}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{F63B2561-6C6C-4010-A63A-AAB03F8C3E30}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{F63B2561-6C6C-4010-A63A-AAB03F8C3E30}.Release|x64.Build.0 = Release|Any CPU\n\t\t{F63B2561-6C6C-4010-A63A-AAB03F8C3E30}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{F63B2561-6C6C-4010-A63A-AAB03F8C3E30}.Release|x86.Build.0 = Release|Any CPU\n\t\t{1E662F33-8F91-48EB-A659-594E7039C65A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{1E662F33-8F91-48EB-A659-594E7039C65A}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{1E662F33-8F91-48EB-A659-594E7039C65A}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{1E662F33-8F91-48EB-A659-594E7039C65A}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{1E662F33-8F91-48EB-A659-594E7039C65A}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{1E662F33-8F91-48EB-A659-594E7039C65A}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{1E662F33-8F91-48EB-A659-594E7039C65A}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{1E662F33-8F91-48EB-A659-594E7039C65A}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{1E662F33-8F91-48EB-A659-594E7039C65A}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{1E662F33-8F91-48EB-A659-594E7039C65A}.Release|x64.Build.0 = Release|Any CPU\n\t\t{1E662F33-8F91-48EB-A659-594E7039C65A}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{1E662F33-8F91-48EB-A659-594E7039C65A}.Release|x86.Build.0 = Release|Any CPU\n\t\t{FAC71622-8310-4139-944B-F1FBF6588843}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{FAC71622-8310-4139-944B-F1FBF6588843}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{FAC71622-8310-4139-944B-F1FBF6588843}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{FAC71622-8310-4139-944B-F1FBF6588843}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{FAC71622-8310-4139-944B-F1FBF6588843}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{FAC71622-8310-4139-944B-F1FBF6588843}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{FAC71622-8310-4139-944B-F1FBF6588843}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{FAC71622-8310-4139-944B-F1FBF6588843}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{FAC71622-8310-4139-944B-F1FBF6588843}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{FAC71622-8310-4139-944B-F1FBF6588843}.Release|x64.Build.0 = Release|Any CPU\n\t\t{FAC71622-8310-4139-944B-F1FBF6588843}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{FAC71622-8310-4139-944B-F1FBF6588843}.Release|x86.Build.0 = Release|Any CPU\n\t\t{8D57B4D2-AB2E-41D4-AE7D-D6A4A173A40F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{8D57B4D2-AB2E-41D4-AE7D-D6A4A173A40F}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{8D57B4D2-AB2E-41D4-AE7D-D6A4A173A40F}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{8D57B4D2-AB2E-41D4-AE7D-D6A4A173A40F}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{8D57B4D2-AB2E-41D4-AE7D-D6A4A173A40F}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{8D57B4D2-AB2E-41D4-AE7D-D6A4A173A40F}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{8D57B4D2-AB2E-41D4-AE7D-D6A4A173A40F}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{8D57B4D2-AB2E-41D4-AE7D-D6A4A173A40F}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{8D57B4D2-AB2E-41D4-AE7D-D6A4A173A40F}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{8D57B4D2-AB2E-41D4-AE7D-D6A4A173A40F}.Release|x64.Build.0 = Release|Any CPU\n\t\t{8D57B4D2-AB2E-41D4-AE7D-D6A4A173A40F}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{8D57B4D2-AB2E-41D4-AE7D-D6A4A173A40F}.Release|x86.Build.0 = Release|Any CPU\n\t\t{698A0646-07E5-4A43-8D02-229BF3571086}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{698A0646-07E5-4A43-8D02-229BF3571086}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{698A0646-07E5-4A43-8D02-229BF3571086}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{698A0646-07E5-4A43-8D02-229BF3571086}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{698A0646-07E5-4A43-8D02-229BF3571086}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{698A0646-07E5-4A43-8D02-229BF3571086}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{698A0646-07E5-4A43-8D02-229BF3571086}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{698A0646-07E5-4A43-8D02-229BF3571086}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{698A0646-07E5-4A43-8D02-229BF3571086}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{698A0646-07E5-4A43-8D02-229BF3571086}.Release|x64.Build.0 = Release|Any CPU\n\t\t{698A0646-07E5-4A43-8D02-229BF3571086}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{698A0646-07E5-4A43-8D02-229BF3571086}.Release|x86.Build.0 = Release|Any CPU\n\t\t{D51F509E-9970-4454-B246-0970FF6C69CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{D51F509E-9970-4454-B246-0970FF6C69CC}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{D51F509E-9970-4454-B246-0970FF6C69CC}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{D51F509E-9970-4454-B246-0970FF6C69CC}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{D51F509E-9970-4454-B246-0970FF6C69CC}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{D51F509E-9970-4454-B246-0970FF6C69CC}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{D51F509E-9970-4454-B246-0970FF6C69CC}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{D51F509E-9970-4454-B246-0970FF6C69CC}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{D51F509E-9970-4454-B246-0970FF6C69CC}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{D51F509E-9970-4454-B246-0970FF6C69CC}.Release|x64.Build.0 = Release|Any CPU\n\t\t{D51F509E-9970-4454-B246-0970FF6C69CC}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{D51F509E-9970-4454-B246-0970FF6C69CC}.Release|x86.Build.0 = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\n\tGlobalSection(ExtensibilityGlobals) = postSolution\n\t\tSolutionGuid = {DBCC3BDC-8B47-46D6-A037-B71BC30D9B0A}\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "WPF/ControlPanel/App.xaml",
    "content": "﻿<Application x:Class=\"ControlPanel.App\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n             StartupUri=\"MainWindow.xaml\">\n    <Application.Resources>\n        <ResourceDictionary>\n            <ResourceDictionary.MergedDictionaries>\n                <ResourceDictionary Source=\"ControlPanel.xaml\" />\n            </ResourceDictionary.MergedDictionaries>\n        </ResourceDictionary>\n    </Application.Resources>\n</Application>"
  },
  {
    "path": "WPF/ControlPanel/App.xaml.cs",
    "content": "﻿using System.Windows;\n\nnamespace ControlPanel\n{\n    /// <summary>\n    ///     Interaction logic for App.xaml\n    /// </summary>\n    public partial class App : Application\n    {\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/AssemblyInfo.cs",
    "content": "using System.Windows;\n\n[assembly: ThemeInfo(\n    ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located\n    //(used if a resource is not found in the page,\n    // or application resource dictionaries)\n    ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located\n    //(used if a resource is not found in the page,\n    // app, or any theme specific resource dictionaries)\n)]"
  },
  {
    "path": "WPF/ControlPanel/COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "WPF/ControlPanel/ControlPanel.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <OutputType>WinExe</OutputType>\n        <TargetFrameworks>net6.0-windows</TargetFrameworks>\n        <Nullable>enable</Nullable>\n        <UseWPF>true</UseWPF>\n        <CsWinRTEnabled>false</CsWinRTEnabled>\n        <LangVersion>11</LangVersion>\n    </PropertyGroup>\n\n    <ItemGroup>\n        <EmbeddedResource Update=\"Resources\\Langs.resx\" Generator=\"ResXFileCodeGenerator\" LastGenOutput=\"Langs.Designer.cs\" />\n    </ItemGroup>\n\n    <ItemGroup>\n        <PackageReference Include=\"Fody\" Version=\"6.6.4\">\n            <PrivateAssets>all</PrivateAssets>\n            <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n        </PackageReference>\n        <PackageReference Include=\"MaterialDesignThemes\" Version=\"4.8.0\" />\n        <PackageReference Include=\"PropertyChanged.Fody\" Version=\"4.1.0\" PrivateAssets=\"All\" />\n        <PackageReference Include=\"WPFLocalizeExtension\" Version=\"3.10.0\" />\n    </ItemGroup>\n\n    <ItemGroup>\n        <ProjectReference Include=\"..\\..\\Configuration\\Configuration.csproj\" />\n        <ProjectReference Include=\"..\\..\\Ipc\\IpcServer\\IpcServer.csproj\" />\n        <ProjectReference Include=\"..\\..\\VirtualDesktopWrapper\\VirtualDesktopWrapper.csproj\" />\n    </ItemGroup>\n\n    <ItemGroup>\n        <Resource Include=\"Resources\\Images\\AboutLogo_2.png\" />\n        <Resource Include=\"Resources\\Images\\m0.png\" />\n        <Resource Include=\"Resources\\Images\\m1.png\" />\n        <Resource Include=\"Resources\\Images\\m2.png\" />\n        <Resource Include=\"Resources\\Images\\m3.png\" />\n        <Resource Include=\"Resources\\Images\\m4.png\" />\n        <Resource Include=\"Resources\\Images\\m5.png\" />\n        <Resource Include=\"Resources\\Images\\m6.png\" />\n        <Resource Include=\"Resources\\Images\\m7.png\" />\n        <None Remove=\"Resources\\Definitions\\KeyboardTree.json\" />\n        <EmbeddedResource Include=\"Resources\\Definitions\\KeyboardTree.json\" />\n    </ItemGroup>\n\n    <ItemGroup>\n        <Compile Update=\"Resources\\Langs.Designer.cs\">\n            <DesignTime>True</DesignTime>\n            <AutoGen>True</AutoGen>\n            <DependentUpon>Langs.resx</DependentUpon>\n        </Compile>\n    </ItemGroup>\n\n    <ItemGroup>\n      <Page Update=\"Pages\\Control.xaml\">\n        <Generator>MSBuild:Compile</Generator>\n        <XamlRuntime>Wpf</XamlRuntime>\n        <SubType>Designer</SubType>\n      </Page>\n    </ItemGroup>\n\n    <PropertyGroup>\n        <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>\n        <SatelliteResourceLanguages>en-US,zh-Hans</SatelliteResourceLanguages>\n    </PropertyGroup>\n\n</Project>\n"
  },
  {
    "path": "WPF/ControlPanel/ControlPanel.xaml",
    "content": "﻿<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml\" />\n    </ResourceDictionary.MergedDictionaries>\n    <Image x:Key=\"Logo\" Margin=\"10\" Width=\"50\" Height=\"50\" Source=\"Resources/Images/AboutLogo_2.png\" />\n    <Image x:Key=\"M0\" Source=\"Resources/Images/m0.png\" />\n    <Image x:Key=\"M1\" Source=\"Resources/Images/m1.png\" />\n    <Image x:Key=\"M2\" Source=\"Resources/Images/m2.png\" />\n    <Image x:Key=\"M3\" Source=\"Resources/Images/m3.png\" />\n    <Image x:Key=\"M4\" Source=\"Resources/Images/m4.png\" />\n    <Image x:Key=\"M5\" Source=\"Resources/Images/m5.png\" />\n    <Image x:Key=\"M6\" Source=\"Resources/Images/m6.png\" />\n    <Image x:Key=\"M7\" Source=\"Resources/Images/m7.png\" />\n</ResourceDictionary>"
  },
  {
    "path": "WPF/ControlPanel/Converters/CheckBoxConverter.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Globalization;\nusing System.Windows.Data;\n\nnamespace ControlPanel.Converters;\n\npublic class CheckBoxConverter : IValueConverter\n{\n    public object Convert( object value, Type targetType, object parameter, CultureInfo culture )\n    {\n        return value != null && ( value.ToString()?.Equals( parameter ) ?? false );\n    }\n\n    public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )\n    {\n        return value != null && value.Equals( true ) ? parameter : Binding.DoNothing;\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Converters/CheckBoxStateByIndexConverter.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Globalization;\nusing System.Windows.Data;\n\nnamespace ControlPanel.Converters;\n\npublic class CheckBoxStateByIndexConverter : IValueConverter\n{\n    public object Convert( object value, Type targetType, object parameter, CultureInfo culture )\n    {\n        return value is >= 0;\n    }\n\n    public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )\n    {\n        throw new NotImplementedException();\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Converters/DrawerStateMutexConverter.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Globalization;\nusing System.Windows;\nusing System.Windows.Data;\n\nnamespace ControlPanel.Converters;\n\npublic class DrawerStateMutexConverter : IValueConverter\n{\n    public object Convert( object value, Type targetType, object parameter, CultureInfo culture )\n    {\n        return (bool)value ? Visibility.Hidden : Visibility.Visible;\n    }\n\n    public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )\n    {\n        throw new NotImplementedException();\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Converters/LocConverter.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Globalization;\nusing System.Windows.Data;\n\nnamespace ControlPanel.Converters;\n\npublic class LocConverter : IValueConverter\n{\n    public object Convert( object value, Type targetType, object parameter, CultureInfo culture )\n    {\n        return parameter.ToString() + value;\n    }\n\n    public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )\n    {\n        throw new NotImplementedException();\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Converters/MouseActionConverter.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Globalization;\nusing System.Windows.Data;\nusing System.Windows.Forms;\nusing VirtualSpace.Config;\n\nnamespace ControlPanel.Converters;\n\npublic class MouseActionConverter : IMultiValueConverter\n{\n    public object Convert( object[] values, Type targetType, object parameter, CultureInfo culture )\n    {\n        if ( values.Length == 0 ) return null;\n\n        var prefix = values[0].ToString() == MouseAction.MOUSE_NODE_DESKTOP_PREFIX ? MouseAction.MOUSE_NODE_DESKTOP_PREFIX : MouseAction.MOUSE_NODE_WINDOW_PREFIX;\n        var mks    = Keys.None;\n        if ( (bool)values[1] ) mks |= Keys.LWin;\n        if ( (bool)values[2] ) mks |= Keys.Control;\n        if ( (bool)values[3] ) mks |= Keys.Alt;\n        if ( (bool)values[4] ) mks |= Keys.Shift;\n\n        var mb      = values[5];\n        var keyCode = ( (int)mks ).ToString( \"X2\" );\n\n        var maId = prefix + keyCode + MouseAction.KEY_SPLITTER + mb;\n\n        if ( Manager.Configs.MouseActions.ContainsKey( maId ) )\n        {\n            return Manager.Configs.MouseActions[maId].ToString();\n        }\n\n        return MouseAction.Action.DoNothing.ToString();\n    }\n\n    public object[] ConvertBack( object value, Type[] targetTypes, object parameter, CultureInfo culture )\n    {\n        throw new NotImplementedException();\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Converters/RuleFieldConverter.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Globalization;\nusing System.Linq;\nusing System.Text.Json;\nusing System.Windows;\nusing System.Windows.Controls;\nusing System.Windows.Data;\nusing ControlPanel.ViewModels;\nusing VirtualSpace.Config.Events.Expression;\n\nnamespace ControlPanel.Converters;\n\npublic class RuleFieldConverter : IMultiValueConverter\n{\n    public object Convert( object[] values, Type targetType, object parameter, CultureInfo culture )\n    {\n        var type = parameter.ToString();\n\n        if ( type == \"V\" )\n        {\n            return ForValue( values );\n        }\n\n        if ( type == typeof( ComboBox ).FullName )\n        {\n            return ForCombobox( values );\n        }\n\n        if ( type == typeof( CheckBox ).FullName )\n        {\n            return ForCheckBox( values );\n        }\n\n        if ( type == typeof( TextBox ).FullName )\n        {\n            return ForTextBox( values );\n        }\n\n        return null;\n    }\n\n    private static int ForValue( object[] values )\n    {\n        if ( values is null || values[0] is null ||\n             values[0] == DependencyProperty.UnsetValue ||\n             values[1] == DependencyProperty.UnsetValue ) return 0;\n\n        try\n        {\n            var jsonDocument       = (JsonDocument)values[0];\n            var expressionTemplate = Conditions.ParseExpressionTemplate( jsonDocument );\n            foreach ( var r in expressionTemplate.rules )\n            {\n                if ( r.field == values[1].ToString() )\n                {\n                    var index = RulesViewModel.Screens.Select( ( vv, index ) => new {nv = vv, index} )\n                        .Where( pair => ( (dynamic)pair.nv ).Value.ToString() == r.value.V )\n                        .Select( pair => pair.index + 1 )\n                        .FirstOrDefault() - 1;\n\n                    return index;\n                }\n            }\n        }\n        catch\n        {\n            return 0;\n        }\n\n        return 0;\n    }\n\n    private static int ForCombobox( object[] values )\n    {\n        if ( values is null || values[0] is null ||\n             values[0] == DependencyProperty.UnsetValue ||\n             values[1] == DependencyProperty.UnsetValue ) return 0;\n\n        try\n        {\n            var jsonDocument       = (JsonDocument)values[0];\n            var expressionTemplate = Conditions.ParseExpressionTemplate( jsonDocument );\n            foreach ( var r in expressionTemplate.rules )\n            {\n                if ( r.field == values[1].ToString() )\n                {\n                    var index = RulesViewModel.Operators.Select( ( v, index ) => new {value = v, index} )\n                        .Where( pair => ( (dynamic)pair.value ).Value.ToString() == r.@operator )\n                        .Select( pair => pair.index + 1 )\n                        .FirstOrDefault() - 1;\n\n                    return index;\n                }\n            }\n        }\n        catch\n        {\n            return 0;\n        }\n\n        return 0;\n    }\n\n    private static bool ForCheckBox( object[] values )\n    {\n        if ( values is null || values[0] is null ||\n             values[0] == DependencyProperty.UnsetValue ||\n             values[1] == DependencyProperty.UnsetValue ) return false;\n\n        try\n        {\n            var jsonDocument       = (JsonDocument)values[0];\n            var expressionTemplate = Conditions.ParseExpressionTemplate( jsonDocument );\n            foreach ( var r in expressionTemplate.rules )\n            {\n                if ( r.field == values[1].ToString() )\n                {\n                    return true;\n                }\n            }\n        }\n        catch\n        {\n            return false;\n        }\n\n        return false;\n    }\n\n    private static string ForTextBox( object[] values )\n    {\n        if ( values is null || values[0] is null ||\n             values[0] == DependencyProperty.UnsetValue ||\n             values[1] == DependencyProperty.UnsetValue ) return \"\";\n\n        try\n        {\n            var jsonDocument       = (JsonDocument)values[0];\n            var expressionTemplate = Conditions.ParseExpressionTemplate( jsonDocument );\n            foreach ( var r in expressionTemplate.rules )\n            {\n                if ( r.field == values[1].ToString() )\n                {\n                    return r.value.V;\n                }\n            }\n        }\n        catch\n        {\n            return \"\";\n        }\n\n        return \"\";\n    }\n\n    public object[] ConvertBack( object value, Type[] targetTypes, object parameter, CultureInfo culture )\n    {\n        throw new NotImplementedException();\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Converters/RuleFieldFromControlNameConverter.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Globalization;\nusing System.Windows.Data;\n\nnamespace ControlPanel.Converters;\n\npublic class RuleFieldFromControlNameConverter : IValueConverter\n{\n    public object Convert( object value, Type targetType, object parameter, CultureInfo culture )\n    {\n        var name = value as string;\n        return name.Split( \"_\" )[1];\n    }\n\n    public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )\n    {\n        return int.Parse( value.ToString() );\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Converters/RuleFormDefaultValueConverter.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Globalization;\nusing System.Windows.Data;\n\nnamespace ControlPanel.Converters;\n\npublic class RuleFormDefaultValueConverter : IValueConverter\n{\n    public object Convert( object value, Type targetType, object parameter, CultureInfo culture )\n    {\n        var v = (int)value;\n        return v < 0 ? 0 : v;\n    }\n\n    public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )\n    {\n        throw new NotImplementedException();\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Converters/RuleHeaderByStateConverter.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Globalization;\nusing System.Windows.Data;\n\nnamespace ControlPanel.Converters;\n\npublic class RuleHeaderByStateConverter : IValueConverter\n{\n    public object Convert( object value, Type targetType, object parameter, CultureInfo culture )\n    {\n        var guid = (Guid)value;\n        return guid == Guid.Empty ? \"Page.Rules.NewRule\" : \"Page.Rules.EditRule\";\n    }\n\n    public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )\n    {\n        throw new NotImplementedException();\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Converters/ThemeConverter.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Globalization;\nusing System.Windows.Data;\n\nnamespace ControlPanel.Converters;\n\npublic class ThemeConverter : IValueConverter\n{\n    public object Convert( object value, Type targetType, object parameter, CultureInfo culture )\n    {\n        return (int)value;\n    }\n\n    public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )\n    {\n        return int.Parse( value.ToString() );\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Converters/UIButtonStyleByVdAConverter.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Globalization;\nusing System.Windows.Data;\nusing System.Windows.Media;\n\nnamespace ControlPanel.Converters;\n\npublic class UIButtonStyleByVdAConverter : IMultiValueConverter\n{\n    public object Convert( object[] values, Type targetType, object parameter, CultureInfo culture )\n    {\n        if ( parameter.ToString() == \"B\" )\n        {\n            var vda         = (int)values[0];\n            var buttonIndex = int.Parse( values[1].ToString() );\n            return vda == buttonIndex ? new SolidColorBrush( Colors.Pink ) : new SolidColorBrush( Colors.LightGray );\n        }\n\n        var count = (int)values[0];\n        return GetFlag( count ) || values[1].ToString() == \"0\";\n    }\n\n    public object[] ConvertBack( object value, Type[] targetTypes, object parameter, CultureInfo culture )\n    {\n        throw new NotImplementedException();\n    }\n\n    private static bool GetFlag( int num )\n    {\n        var result = Math.Sqrt( num );\n        return result % 1 == 0;\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Converters/WidthHeightConverter.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Globalization;\nusing System.Windows.Data;\n\nnamespace ControlPanel.Converters;\n\npublic class WidthHeightConverter : IValueConverter\n{\n    public object Convert( object value, Type targetType, object parameter, CultureInfo culture )\n    {\n        return (double)value - double.Parse( parameter.ToString() );\n    }\n\n    public object ConvertBack( object value, Type targetTypes, object parameter, CultureInfo culture )\n    {\n        throw new NotImplementedException();\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/ExportResourceDictionary.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of ControlPanel.\n// \n// ControlPanel is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// ControlPanel is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with ControlPanel. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.Windows.Markup;\n\n[assembly: XmlnsDefinition( \"http://newlooper.com/virtualspace/share\", \"ControlPanel\" )]\n\nnamespace ControlPanel;\n\npublic partial class ExportResourceDictionary\n{\n    public static ExportResourceDictionary Instance { get; } = new ExportResourceDictionary();\n\n    public ExportResourceDictionary()\n    {\n        InitializeComponent();\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/ExportResourceDictionary.xaml",
    "content": "﻿<ResourceDictionary x:Class=\"ControlPanel.ExportResourceDictionary\"\n                    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"ControlPanel.xaml\" />\n    </ResourceDictionary.MergedDictionaries>\n</ResourceDictionary>"
  },
  {
    "path": "WPF/ControlPanel/Factories/NavBarItem.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.Collections.Generic;\nusing System.Windows;\nusing System.Windows.Controls;\nusing MaterialDesignThemes.Wpf;\nusing WPFLocalizeExtension.Extensions;\n\nnamespace ControlPanel.Factories;\n\npublic class NavBarItem : TabItem\n{\n    public static readonly Dictionary<string, (PackIconKind kind, string locKey)> NavBarItemsInfo = new()\n    {\n        {\"General\", ( PackIconKind.MonitorDashboard, \"NavBar.General\" )},\n        {\"UI\", ( PackIconKind.TableAccount, \"NavBar.UI\" )},\n        {\"Control\", ( PackIconKind.CursorPointer, \"NavBar.Control\" )},\n        {\"Rules\", ( PackIconKind.BookOpenPageVariant, \"NavBar.Rules\" )},\n        {\"Plugins\", ( PackIconKind.ToyBrickMarkerOutline, \"NavBar.Plugins\" )},\n        {\"Logs\", ( PackIconKind.BookSearchOutline, \"NavBar.Logs\" )},\n        {\"About\", ( PackIconKind.HelpBox, \"NavBar.About\" )},\n    };\n\n    private NavBarItem( string tag, PackIconKind kind, string locKey )\n    {\n        var stackPanel = new StackPanel\n        {\n            Width = double.NaN,\n            Height = double.NaN\n        };\n        var packIcon = new PackIcon\n        {\n            Width = 24,\n            Height = 24,\n            HorizontalAlignment = HorizontalAlignment.Center,\n            Kind = kind\n        };\n        var tb = new TextBlock\n        {\n            HorizontalAlignment = HorizontalAlignment.Center\n        };\n\n        new LocExtension( locKey ).SetBinding( tb, TextBlock.TextProperty );\n\n        stackPanel.Children.Add( packIcon );\n        stackPanel.Children.Add( tb );\n        Header = stackPanel;\n        Tag = tag;\n    }\n\n    public static void InitNavBar( TabControl tc )\n    {\n        foreach ( var kv in NavBarItemsInfo )\n            tc.Items.Add( new NavBarItem( kv.Key, kv.Value.kind, kv.Value.locKey ) );\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Factories/PageFactory.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.Windows.Controls;\nusing ControlPanel.Pages;\nusing MaterialDesignThemes.Wpf;\nusing Control = ControlPanel.Pages.Control;\n\nnamespace ControlPanel.Factories;\n\npublic static class PageFactory\n{\n    public static UserControl GetPage( (PackIconKind kind, string locKey) info )\n    {\n        return info.locKey switch\n        {\n            \"NavBar.General\" => General.Create( info.locKey, info.kind ),\n            \"NavBar.UI\" => UI.Create( info.locKey, info.kind ),\n            \"NavBar.Rules\" => Rules.Create( info.locKey, info.kind ),\n            \"NavBar.Control\" => Control.Create( info.locKey, info.kind ),\n            \"NavBar.Plugins\" => Plugins.Create( info.locKey, info.kind ),\n            \"NavBar.Logs\" => Logs.Create( info.locKey, info.kind ),\n            \"NavBar.About\" => Help.Instance,\n            \"NavBar.Settings\" => Settings.Create(),\n            _ => General.Create( info.locKey, info.kind )\n        };\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/FodyWeavers.xml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Weavers xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"FodyWeavers.xsd\">\n    <PropertyChanged/>\n</Weavers>"
  },
  {
    "path": "WPF/ControlPanel/MainWindow.logs.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System.Threading;\nusing System.Threading.Channels;\nusing ControlPanel.Pages;\nusing VirtualSpace.AppLogs;\n\nnamespace ControlPanel;\n\n/// <summary>\n///     Interaction logic for MainWindow.xaml\n/// </summary>\npublic partial class MainWindow\n{\n    private static readonly Channel<LogMessage>     LogChannel               = Logger.LogChannel;\n    private readonly        CancellationTokenSource _cancelTokenSourceForLog = new();\n\n    private async void PickLogAndWrite( CancellationToken stoppingToken )\n    {\n        try\n        {\n            while ( await LogChannel.Reader.WaitToReadAsync( stoppingToken ) )\n            {\n                if ( LogChannel.Reader.TryRead( out var message ) )\n                {\n                    Logs.Append( message.Message, message.Type );\n                }\n            }\n        }\n        catch\n        {\n            // ignored\n        }\n        finally\n        {\n            _cancelTokenSourceForLog.Dispose();\n        }\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/MainWindow.theme.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.Windows.Media;\nusing MaterialDesignColors;\nusing MaterialDesignThemes.Wpf;\nusing VirtualSpace.Config;\nusing VirtualSpace.Helpers;\n\nnamespace ControlPanel;\n\npublic partial class MainWindow\n{\n    private (Color pColor, Color sColor, IBaseTheme theme) GetThemeInfo()\n    {\n        var   theme = Theme.Light;\n        Color pColor;\n        Color sColor;\n\n        var pColorDark = SwatchHelper.Lookup[(MaterialDesignColor)PrimaryColor.Blue];\n        var sColorDark = SwatchHelper.Lookup[(MaterialDesignColor)SecondaryColor.LightBlue];\n\n        var pColorLight = SwatchHelper.Lookup[(MaterialDesignColor)PrimaryColor.Amber];\n        var sColorLight = SwatchHelper.Lookup[(MaterialDesignColor)SecondaryColor.Yellow];\n\n        switch ( Manager.CurrentProfile.UI.Theme )\n        {\n            case 0:\n                theme = SysInfo.GetAppsTheme() == SysInfo.WinAppsTheme.LIGHT ? Theme.Light : Theme.Dark;\n                pColor = theme == Theme.Dark ? pColorDark : pColorLight;\n                sColor = theme == Theme.Dark ? sColorDark : sColorLight;\n                break;\n            case 1:\n                pColor = pColorLight;\n                sColor = sColorLight;\n                theme = Theme.Light;\n                break;\n            case 2:\n                pColor = pColorDark;\n                sColor = sColorDark;\n                theme = Theme.Dark;\n                break;\n        }\n\n        return ( pColor, sColor, theme );\n    }\n\n    private void InitTheme()\n    {\n        UpdateTheme();\n        RegValueMonitor.OnRegValueChanged += ( o, args ) =>\n        {\n            if ( Manager.CurrentProfile.UI.Theme != 0 ) return;\n            var theme = Resources.GetTheme();\n            var (pColor, sColor, newTheme) = GetThemeInfo();\n            theme.SetPrimaryColor( pColor );\n            theme.SetSecondaryColor( sColor );\n            theme.SetBaseTheme( newTheme );\n            Dispatcher.Invoke( () => { Resources.SetTheme( theme ); } );\n        };\n    }\n\n    public static void UpdateTheme()\n    {\n        var (primaryColor, secondaryColor, initTheme) = _instance.GetThemeInfo();\n        _instance.Resources.SetTheme( Theme.Create( initTheme, primaryColor, secondaryColor ) );\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/MainWindow.xaml",
    "content": "﻿<Window x:Class=\"ControlPanel.MainWindow\"\n        xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n        xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n        xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n        xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n        xmlns:lex=\"http://wpflocalizeextension.codeplex.com\"\n        xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n        lex:LocalizeDictionary.OutputMissingKeys=\"True\"\n        lex:ResxLocalizationProvider.DefaultAssembly=\"ControlPanel\"\n        lex:ResxLocalizationProvider.DefaultDictionary=\"Langs\"\n        mc:Ignorable=\"d\"\n        TextElement.Foreground=\"{DynamicResource MaterialDesignBody}\"\n        TextElement.FontWeight=\"Regular\"\n        TextElement.FontSize=\"14\"\n        TextOptions.TextFormattingMode=\"Ideal\"\n        TextOptions.TextRenderingMode=\"Auto\"\n        Background=\"{DynamicResource MaterialDesignPaper}\"\n        FontFamily=\"Segoe UI,Segoe UI Emoji,Segoe UI Symbol,Microsoft YaHei UI,Microsoft YaHei\"\n        Height=\"800\" Width=\"1280\"\n        Loaded=\"MainWindow_OnLoaded\" Closing=\"MainWindow_OnClosing\">\n\n    <Grid>\n        <Grid.ColumnDefinitions>\n            <ColumnDefinition Width=\"71\" />\n            <ColumnDefinition />\n        </Grid.ColumnDefinitions>\n\n        <materialDesign:Card materialDesign:ElevationAssist.Elevation=\"Dp8\">\n            <DockPanel Background=\"{Binding Background, ElementName=NavBar}\">\n                <TabControl DockPanel.Dock=\"Top\" x:Name=\"NavBar\"\n                            Style=\"{StaticResource MaterialDesignNavigationRailTabControl}\"\n                            SelectionChanged=\"NavBar_OnSelectionChanged\">\n                    <materialDesign:NavigationRailAssist.FloatingContent>\n                        <StaticResource ResourceKey=\"Logo\" />\n                    </materialDesign:NavigationRailAssist.FloatingContent>\n                </TabControl>\n\n                <TabControl DockPanel.Dock=\"Bottom\"\n                            materialDesign:ColorZoneAssist.Mode=\"Standard\"\n                            VerticalAlignment=\"Bottom\"\n                            Style=\"{StaticResource MaterialDesignNavigationRailTabControl}\">\n                    <materialDesign:NavigationRailAssist.FloatingContent>\n                        <Button\n                            Margin=\"16\"\n                            Content=\"{materialDesign:PackIcon Kind=Gear}\"\n                            Style=\"{StaticResource MaterialDesignFloatingActionMiniButton}\"\n                            Click=\"SettingsButton_OnClick\" />\n                    </materialDesign:NavigationRailAssist.FloatingContent>\n                </TabControl>\n            </DockPanel>\n        </materialDesign:Card>\n\n        <materialDesign:Card Grid.Column=\"1\" x:Name=\"ContentFrame\" />\n    </Grid>\n\n</Window>"
  },
  {
    "path": "WPF/ControlPanel/MainWindow.xaml.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.ComponentModel;\nusing System.Diagnostics;\nusing System.Globalization;\nusing System.Windows;\nusing System.Windows.Controls;\nusing System.Windows.Interop;\nusing ControlPanel.Factories;\nusing ControlPanel.Pages;\nusing VirtualSpace;\nusing VirtualSpace.Config;\nusing VirtualSpace.VirtualDesktop.Api;\nusing WPFLocalizeExtension.Engine;\n\nnamespace ControlPanel;\n\n/// <summary>\n///     Interaction logic for MainWindow.xaml\n/// </summary>\npublic partial class MainWindow : Window, IAppController\n{\n    private static MainWindow _instance;\n    private static IntPtr     _handle;\n\n    private IntPtr _mainWindowHandle;\n\n    public MainWindow()\n    {\n        InitializeComponent();\n\n        _instance = this;\n\n        Title = Const.Window.VS_CONTROLLER_TITLE;\n        Topmost = true;\n\n        LocalizeDictionary.Instance.SetCurrentThreadCulture = true;\n        LocalizeDictionary.Instance.Culture = new CultureInfo( Manager.CurrentProfile.UI.Language );\n        NavBarItem.InitNavBar( NavBar );\n\n        new WindowInteropHelper( this ).EnsureHandle();\n    }\n\n    public void ForceLoad()\n    {\n        if ( IsVisible ) return;\n        \n        ShowInTaskbar = false;\n        Left = Const.FakeHideX;\n        Top = Const.FakeHideY;\n        Show();\n        Hide();\n        ShowInTaskbar = true;\n    }\n\n    protected override void OnSourceInitialized( EventArgs e )\n    {\n        base.OnSourceInitialized( e );\n        _handle = new WindowInteropHelper( this ).EnsureHandle();\n    }\n\n    public static IntPtr MainWindowHandle => _instance._mainWindowHandle;\n\n    public void BringToTop()\n    {\n        Left = ( SystemParameters.PrimaryScreenWidth - Width ) / 2;\n        Top = ( SystemParameters.PrimaryScreenHeight - Height ) / 2;\n\n        if ( WindowState == WindowState.Minimized )\n        {\n            WindowState = WindowState.Normal;\n        }\n\n        if ( IsVisible )\n        {\n            DesktopWrapper.MoveWindowToDesktop( _handle, DesktopWrapper.CurrentIndex );\n        }\n        else\n        {\n            Show();\n        }\n\n        Topmost = false;\n        Topmost = true;\n    }\n\n    public void SetMainWindowHandle( IntPtr handle )\n    {\n        _mainWindowHandle = handle;\n    }\n\n    public void Quit()\n    {\n        Closing -= MainWindow_OnClosing;\n        Close();\n    }\n\n    public void RenderDesktopArrangementButtons( string selectedDa )\n    {\n        // throw new NotImplementedException();\n    }\n\n    public void CreateRuleFromWindowHandle( IntPtr handle )\n    {\n        ForceLoad();\n        RuleEditorWindow.Create( handle ).ShowDialog();\n    }\n\n    private void MainWindow_OnLoaded( object sender, RoutedEventArgs e )\n    {\n        InitTheme();\n        PickLogAndWrite( _cancelTokenSourceForLog.Token );\n    }\n\n    private void MainWindow_OnClosing( object? sender, CancelEventArgs e )\n    {\n        if ( Application.Current is App ) return;\n        e.Cancel = true;\n        Hide();\n    }\n\n    public static void TryClose()\n    {\n        _instance.Close();\n    }\n\n    public static void TryQuit()\n    {\n        _instance.Quit();\n    }\n\n    public static void RestartApp( bool runas = false )\n    {\n        var psi = new ProcessStartInfo\n        {\n            FileName = Environment.ProcessPath,\n            UseShellExecute = true\n        };\n\n        if ( runas ) psi.Verb = \"runas\";\n\n        try\n        {\n            Process.Start( psi );\n            Application.Current.Shutdown();\n        }\n        catch\n        {\n            //\n        }\n    }\n\n    private void NavBar_OnSelectionChanged( object sender, SelectionChangedEventArgs e )\n    {\n        var tab = (TabControl)sender;\n        if ( tab.SelectedIndex == -1 ) return;\n        var selectedTab = (TabItem)tab.SelectedItem;\n        ContentFrame.Content = PageFactory.GetPage( NavBarItem.NavBarItemsInfo[selectedTab.Tag.ToString()] );\n    }\n\n    private void SettingsButton_OnClick( object sender, RoutedEventArgs e )\n    {\n        NavBar.SelectedIndex = -1;\n        ContentFrame.Content = Settings.Create();\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Pages/Control.keyboard.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.IO;\nusing System.Reflection;\nusing System.Text.Json;\nusing System.Windows;\nusing System.Windows.Controls;\nusing System.Windows.Input;\nusing ControlPanel.ViewModels;\nusing MaterialDesignThemes.Wpf;\nusing VirtualSpace;\nusing VirtualSpace.Config;\nusing VirtualSpace.Helpers;\nusing VirtualSpace.VirtualDesktop.Api;\n\nnamespace ControlPanel.Pages;\n\npublic partial class Control\n{\n    private void KeyboardTreeView_OnSelectedItemChanged( object sender, RoutedPropertyChangedEventArgs<object> e )\n    {\n        var vm = KeyBindingBox.DataContext as KeyBindingModel;\n        vm.BoxVisible = Visibility.Hidden;\n\n        var selectedNode = e.NewValue as TreeViewItem;\n        if ( selectedNode is null ) return;\n\n        var kbInConfig = Manager.Configs.KeyBindings;\n        var hotkeyId   = selectedNode.Name;\n\n        if ( !kbInConfig.ContainsKey( hotkeyId ) )\n        {\n            var kb = Const.Hotkey.GetKeyBinding( hotkeyId );\n            if ( kb.MessageId == 0 ) return;\n\n            kbInConfig[hotkeyId] = kb;\n        }\n\n        vm.BoxVisible = Visibility.Visible;\n\n        var stack = GetNodePath( selectedNode );\n\n        var path = \"\";\n        foreach ( var node in stack )\n        {\n            if ( string.IsNullOrEmpty( path ) )\n                path = node.Header.ToString();\n            else\n            {\n                path += \" > \" + node.Header;\n            }\n        }\n\n        vm.Path = path;\n        vm.Extra = Const.Hotkey.GetHotkeyExtra( hotkeyId );\n\n        if ( kbInConfig[hotkeyId].GhkCode == \"\" )\n        {\n            vm.LWin = vm.Ctrl = vm.Alt = vm.Shift = false;\n            vm.Key = Const.Hotkey.NONE;\n            return;\n        }\n\n        var arr = kbInConfig[hotkeyId].GhkCode.Split( Const.Hotkey.SPLITTER );\n        if ( arr.Length == 5 )\n        {\n            vm.LWin = arr[0] != Const.Hotkey.NONE;\n            vm.Ctrl = arr[1] != Const.Hotkey.NONE;\n            vm.Alt = arr[2] != Const.Hotkey.NONE;\n            vm.Shift = arr[3] != Const.Hotkey.NONE;\n\n            vm.Key = arr[4];\n        }\n    }\n\n    private void LoadKeyboardTreeView()\n    {\n        var assembly = Assembly.GetExecutingAssembly();\n        var name     = assembly.GetName().Name;\n\n        using var stream = assembly.GetManifestResourceStream( $\"{name}.Resources.Definitions.KeyboardTree.json\" );\n        using var reader = new StreamReader( stream );\n        var       result = reader.ReadToEnd();\n\n        KeyboardTreeView.Items.Clear();\n\n        BuildTreeView( KeyboardTreeView, JsonDocument.Parse( result ),\n            new ValueTuple<string, string, string, string, string>( \"Name\", \"Header\", \"Tag\", \"IsHidden\", \"Nodes\" ) );\n\n        var nodeDesktop       = KeyboardTreeView.Items[1] as TreeViewItem;\n        var nodeDesktopSwitch = nodeDesktop.Items[0] as TreeViewItem;\n\n        var nodeWindow              = KeyboardTreeView.Items[2] as TreeViewItem;\n        var nodeWindowMove          = nodeWindow.Items[0] as TreeViewItem;\n        var nodeWindowMoveAndFollow = nodeWindow.Items[1] as TreeViewItem;\n\n        for ( var i = 1; i <= DesktopWrapper.Count; i++ )\n        {\n            var item = new TreeViewItem\n            {\n                Header = Agent.Langs.GetString( \"KB.Hotkey.SVD\" ) + i,\n                Name = Const.Hotkey.SVD_TREE_NODE_PREFIX + i,\n                Tag = \"KB.Hotkey.SVD\"\n            };\n            nodeDesktopSwitch.Items.Add( item );\n\n            var item2 = new TreeViewItem\n            {\n                Header = Agent.Langs.GetString( \"KB.Hotkey.MW\" ) + i,\n                Name = Const.Hotkey.MW_TREE_NODE_PREFIX + i,\n                Tag = \"KB.Hotkey.MW\"\n            };\n            nodeWindowMove.Items.Add( item2 );\n\n            var item3 = new TreeViewItem\n            {\n                Header = Agent.Langs.GetString( \"KB.Hotkey.MWF\" ) + i,\n                Name = Const.Hotkey.MWF_TREE_NODE_PREFIX + i,\n                Tag = \"KB.Hotkey.MWF\"\n            };\n            nodeWindowMoveAndFollow.Items.Add( item3 );\n        }\n\n        var item4 = new TreeViewItem\n        {\n            Header = Agent.Langs.GetString( \"KB.Hotkey.SVD_BACK_LAST\" ),\n            Name = Const.Hotkey.SWITCH_BACK_LAST,\n            Tag = \"KB.Hotkey.SVD_BACK_LAST\"\n        };\n        nodeDesktopSwitch.Items.Add( item4 );\n    }\n\n    private static (string keyCode, GlobalHotKey.KeyModifiers keyModifiers) GetGhk( KeyBindingModel kbm )\n    {\n        string ghkCode;\n        var    kms = GlobalHotKey.KeyModifiers.None;\n\n        string GenGhkCode( bool @checked, string code )\n        {\n            return ( @checked ? code : Const.Hotkey.NONE ) + Const.Hotkey.SPLITTER;\n        }\n\n        GlobalHotKey.KeyModifiers GenKm( bool @checked, GlobalHotKey.KeyModifiers km )\n        {\n            return @checked ? km : GlobalHotKey.KeyModifiers.None;\n        }\n\n        if ( string.IsNullOrEmpty( kbm.Key ) )\n        {\n            ghkCode = \"\";\n        }\n        else\n        {\n            ghkCode = GenGhkCode( kbm.LWin, Const.Hotkey.WIN );\n            ghkCode += GenGhkCode( kbm.Ctrl, Const.Hotkey.CTRL );\n            ghkCode += GenGhkCode( kbm.Alt, Const.Hotkey.ALT );\n            ghkCode += GenGhkCode( kbm.Shift, Const.Hotkey.SHIFT );\n\n            kms = GenKm( kbm.LWin, GlobalHotKey.KeyModifiers.WindowsKey );\n            kms |= GenKm( kbm.Ctrl, GlobalHotKey.KeyModifiers.Ctrl );\n            kms |= GenKm( kbm.Alt, GlobalHotKey.KeyModifiers.Alt );\n            kms |= GenKm( kbm.Shift, GlobalHotKey.KeyModifiers.Shift );\n\n            ghkCode += kbm.Key;\n        }\n\n        return new ValueTuple<string, GlobalHotKey.KeyModifiers>( ghkCode, kms );\n    }\n\n    private void SaveHotkey( (string keyCode, GlobalHotKey.KeyModifiers keyModifiers) ghk )\n    {\n        var selectedItem = KeyboardTreeView.SelectedItem as TreeViewItem;\n        var hotkeyId     = selectedItem.Name;\n        var kb           = Const.Hotkey.GetKeyBinding( hotkeyId );\n        kb.GhkCode = ghk.keyCode;\n        Manager.Configs.KeyBindings[hotkeyId] = kb;\n        Manager.Save( reason: kb.GhkCode.Replace( Const.Hotkey.NONE + Const.Hotkey.SPLITTER, \"\" ), reasonName: hotkeyId );\n        ShowTips( Snackbar, Agent.Langs.GetString( \"KB.Hotkey.SettingsSaved\" ) );\n    }\n\n    private void RegHotkey( (string keyCode, GlobalHotKey.KeyModifiers keyModifiers) ghk )\n    {\n        var selectedItem = KeyboardTreeView.SelectedItem as TreeViewItem;\n        var hotkeyId     = selectedItem.Name;\n        var msgId        = Const.Hotkey.GetKeyBinding( hotkeyId ).MessageId;\n        GlobalHotKey.UnregisterHotKey( MainWindow.MainWindowHandle, msgId );\n\n        var vm = KeyBindingBox.DataContext as KeyBindingModel;\n\n        if ( string.IsNullOrEmpty( vm.Key ) || vm.Key == Const.Hotkey.NONE )\n        {\n            return;\n        }\n\n        if ( GlobalHotKey.RegHotKey( MainWindow.MainWindowHandle,\n                msgId,\n                ghk.keyModifiers,\n                KeyInterop.VirtualKeyFromKey( Enum.Parse<Key>( vm.Key ) ) ) )\n        {\n            ShowTips( Snackbar, Agent.Langs.GetString( \"KB.Hotkey.Reg.Success\" ) );\n        }\n        else\n        {\n            ShowTips( Snackbar, Agent.Langs.GetString( \"KB.Hotkey.Reg.Fail\" ) );\n        }\n    }\n\n    private void RegAndSave_OnClick( object sender, RoutedEventArgs e )\n    {\n        var vm = KeyBindingBox.DataContext as KeyBindingModel;\n        if ( vm == null ) return;\n\n        if ( ( vm.LWin | vm.Ctrl | vm.Alt | vm.Shift ) == false )\n        {\n            ShowTips( Snackbar, Agent.Langs.GetString( \"KB.Hotkey.MKeyCheck\" ) );\n            return;\n        }\n\n        if ( string.IsNullOrEmpty( vm.Key ) || vm.Key == Const.Hotkey.NONE )\n        {\n            ShowTips( Snackbar, Agent.Langs.GetString( \"KB.Hotkey.KeyCheck\" ) );\n            return;\n        }\n\n        var ghk = GetGhk( vm );\n        RegHotkey( ghk );\n        SaveHotkey( ghk );\n    }\n\n    private void ClearAndSave_OnClick( object sender, RoutedEventArgs e )\n    {\n        var selectedItem = KeyboardTreeView.SelectedItem as TreeViewItem;\n        if ( selectedItem == null ) return;\n        var hotkeyId = selectedItem.Name;\n\n        var msgId = Const.Hotkey.GetKeyBinding( hotkeyId ).MessageId;\n        GlobalHotKey.UnregisterHotKey( MainWindow.MainWindowHandle, msgId );\n        var vm = KeyBindingBox.DataContext as KeyBindingModel;\n        vm.Clear();\n        Manager.Configs.KeyBindings!.Remove( hotkeyId );\n        Manager.Save( reason: \"clear\", reasonName: hotkeyId );\n    }\n\n    private void ShowTips( Snackbar sb, string msg, int seconds = 1 )\n    {\n        sb.MessageQueue?.Enqueue(\n            msg,\n            null,\n            null,\n            null,\n            false,\n            true,\n            TimeSpan.FromSeconds( seconds ) );\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Pages/Control.mouse.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Windows;\nusing System.Windows.Forms;\nusing ControlPanel.ViewModels;\nusing VirtualSpace.Config;\n\nnamespace ControlPanel.Pages;\n\npublic partial class Control\n{\n    private void DesktopActionBind_OnClick( object sender, RoutedEventArgs e )\n    {\n        MouseActionBind( DesktopMouseActionBox.DataContext as MouseActionModel,\n            MouseAction.MOUSE_NODE_DESKTOP_PREFIX,\n            cbbDesktopActions.SelectedValue.ToString() );\n    }\n\n    private void WindowActionBind_OnClick( object sender, RoutedEventArgs e )\n    {\n        MouseActionBind( WindowMouseActionBox.DataContext as MouseActionModel,\n            MouseAction.MOUSE_NODE_WINDOW_PREFIX,\n            cbbWindowActions.SelectedValue.ToString() );\n    }\n\n    private void MouseActionBind( MouseActionModel vm, string prefix, string actionName )\n    {\n        var mks = Keys.None;\n        if ( vm.LWin ) mks |= Keys.LWin;\n        if ( vm.Ctrl ) mks |= Keys.Control;\n        if ( vm.Alt ) mks |= Keys.Alt;\n        if ( vm.Shift ) mks |= Keys.Shift;\n\n        var mb      = vm.MouseButton;\n        var keyCode = ( (int)mks ).ToString( \"X2\" );\n        var maId    = prefix + keyCode + MouseAction.KEY_SPLITTER + mb;\n\n        var action = (MouseAction.Action)Enum.Parse( typeof( MouseAction.Action ), actionName );\n\n        Manager.Configs.MouseActions[maId] = action;\n        Manager.Save( reason: action, reasonName: maId );\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Pages/Control.tree.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing System.Windows;\nusing System.Windows.Controls;\nusing System.Windows.Media;\nusing VirtualSpace;\n\nnamespace ControlPanel.Pages;\n\npublic partial class Control\n{\n    private static Stack<TreeViewItem> GetNodePath( UIElement element, bool includeSelf = true )\n    {\n        var path = new Stack<TreeViewItem>();\n        var tvi  = element as TreeViewItem;\n\n        if ( includeSelf )\n            path.Push( tvi );\n\n        while ( element != null )\n        {\n            element = VisualTreeHelper.GetParent( element ) as UIElement;\n            tvi = element as TreeViewItem;\n            if ( tvi != null )\n                path.Push( tvi );\n        }\n\n        return path;\n    }\n\n    private static void BuildTreeView( object node, object jsonDoc, (string Name, string Header, string Tag, string IsHidden, string Nodes) keys )\n    {\n        switch ( node )\n        {\n            case TreeView treeView:\n                var nodes = ( (JsonDocument)jsonDoc ).RootElement.GetProperty( keys.Nodes );\n                foreach ( var child in nodes.EnumerateArray() )\n                {\n                    var topLevelNode = new TreeViewItem\n                    {\n                        Header = Agent.Langs.GetString( child.GetProperty( keys.Header ).GetString() ),\n                        IsExpanded = true\n                    };\n\n                    if ( child.TryGetProperty( keys.Name, out var name ) )\n                        topLevelNode.Name = name.GetString();\n\n                    if ( child.TryGetProperty( keys.Nodes, out var subNodes ) )\n                    {\n                        BuildTreeView( topLevelNode, subNodes, keys );\n                    }\n\n                    treeView.Items.Add( topLevelNode );\n                }\n\n                break;\n            case TreeViewItem treeViewItem:\n                foreach ( var child in ( (JsonElement)jsonDoc ).EnumerateArray() )\n                {\n                    var subNode = new TreeViewItem\n                    {\n                        Header = Agent.Langs.GetString( child.GetProperty( keys.Header ).GetString() ),\n                        IsExpanded = true\n                    };\n\n                    if ( child.TryGetProperty( keys.IsHidden, out var isHidden ) && isHidden.GetBoolean() )\n                    {\n                        subNode.Visibility = Visibility.Collapsed;\n                    }\n\n                    if ( child.TryGetProperty( keys.Name, out var name ) )\n                        subNode.Name = name.GetString();\n\n                    if ( child.TryGetProperty( keys.Nodes, out var subNodes ) )\n                    {\n                        BuildTreeView( subNode, subNodes, keys );\n                    }\n\n                    treeViewItem.Items.Add( subNode );\n                }\n\n                break;\n        }\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Pages/Control.xaml",
    "content": "﻿<UserControl x:Class=\"ControlPanel.Pages.Control\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n             xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n             xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n             xmlns:commons=\"clr-namespace:ControlPanel.Pages.Menus.Commons\"\n             xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n             xmlns:lex=\"http://wpflocalizeextension.codeplex.com\"\n             xmlns:config=\"clr-namespace:VirtualSpace.Config;assembly=Configuration\"\n             xmlns:converters=\"clr-namespace:ControlPanel.Converters\"\n             mc:Ignorable=\"d\">\n\n    <UserControl.Resources>\n        <ResourceDictionary>\n            <Style TargetType=\"Button\" BasedOn=\"{StaticResource MaterialDesignPaperSecondaryLightButton}\">\n                <Setter Property=\"Margin\" Value=\"10,5\" />\n                <Setter Property=\"Height\" Value=\"50\" />\n            </Style>\n            <Style TargetType=\"CheckBox\" BasedOn=\"{StaticResource MaterialDesignCheckBox}\">\n                <Setter Property=\"Margin\" Value=\"0,0,10,0\"></Setter>\n                <Setter Property=\"materialDesign:CheckBoxAssist.CheckBoxSize\" Value=\"30\"></Setter>\n            </Style>\n            <converters:LocConverter x:Key=\"LocConverter\" />\n            <converters:MouseActionConverter x:Key=\"MouseActionConverter\" />\n            <x:Static Member=\"config:MouseAction.MOUSE_NODE_DESKTOP_PREFIX\" x:Key=\"madp\"></x:Static>\n            <x:Static Member=\"config:MouseAction.MOUSE_NODE_WINDOW_PREFIX\" x:Key=\"mawp\"></x:Static>\n        </ResourceDictionary>\n    </UserControl.Resources>\n\n    <Grid>\n        <Grid.RowDefinitions>\n            <RowDefinition Height=\"Auto\" />\n            <RowDefinition Height=\"*\" />\n        </Grid.RowDefinitions>\n\n        <commons:MenuContainer x:Name=\"MenuContainer\" Grid.Row=\"0\" />\n\n        <materialDesign:Card Grid.Row=\"1\" materialDesign:ElevationAssist.Elevation=\"Dp2\" Margin=\"10,10,10,12\">\n            <TabControl HorizontalContentAlignment=\"Center\"\n                        materialDesign:ColorZoneAssist.Mode=\"PrimaryLight\"\n                        materialDesign:NavigationRailAssist.SelectionCornerRadius=\"10\"\n                        materialDesign:NavigationRailAssist.ShowSelectionBackground=\"True\"\n                        Style=\"{StaticResource MaterialDesignNavigationRailTabControl}\"\n                        TabStripPlacement=\"Bottom\">\n                <TabItem Margin=\"10,5\">\n                    <TabItem.Header>\n                        <StackPanel Width=\"auto\" Height=\"auto\">\n                            <materialDesign:PackIcon\n                                Width=\"30\" Height=\"30\"\n                                HorizontalAlignment=\"Center\"\n                                Kind=\"Keyboard\" />\n                            <TextBlock HorizontalAlignment=\"Center\" FontSize=\"13\" Text=\"{lex:Loc Page.Control.Keyboard}\" />\n                        </StackPanel>\n                    </TabItem.Header>\n\n                    <Grid>\n                        <Grid.ColumnDefinitions>\n                            <ColumnDefinition Width=\"Auto\"></ColumnDefinition>\n                            <ColumnDefinition Width=\"*\"></ColumnDefinition>\n                        </Grid.ColumnDefinitions>\n                        <Border BorderBrush=\"Gray\" BorderThickness=\"1\" Margin=\"10\">\n                            <TreeView x:Name=\"KeyboardTreeView\"\n                                      MinWidth=\"450\" MaxWidth=\"700\"\n                                      SelectedItemChanged=\"KeyboardTreeView_OnSelectedItemChanged\">\n                                <TreeView.Resources>\n                                    <Style TargetType=\"TreeViewItem\" BasedOn=\"{StaticResource MaterialDesignTreeViewItem}\">\n                                        <Setter Property=\"materialDesign:TreeViewAssist.ExpanderSize\" Value=\"20\" />\n                                        <Setter Property=\"Padding\" Value=\"3\" />\n                                    </Style>\n                                </TreeView.Resources>\n                            </TreeView>\n                        </Border>\n                        <Border x:Name=\"KeyBindingBox\" Visibility=\"{Binding BoxVisible}\" Grid.Column=\"1\"\n                                BorderBrush=\"Gray\" BorderThickness=\"1\" Margin=\"0,10,10,10\">\n                            <StackPanel>\n                                <TextBlock Margin=\"10\" FontSize=\"20\" Text=\"{Binding Path}\"></TextBlock>\n                                <StackPanel Orientation=\"Horizontal\" Margin=\"10\">\n\n                                    <UniformGrid Columns=\"4\">\n                                        <CheckBox IsChecked=\"{Binding LWin}\">LWin</CheckBox>\n                                        <CheckBox IsChecked=\"{Binding Ctrl}\">Ctrl</CheckBox>\n                                        <CheckBox IsChecked=\"{Binding Alt}\">Alt</CheckBox>\n                                        <CheckBox IsChecked=\"{Binding Shift}\">Shift</CheckBox>\n                                    </UniformGrid>\n\n                                    <ComboBox MinWidth=\"200\"\n                                              Style=\"{StaticResource MaterialDesignOutlinedComboBox}\"\n                                              Text=\"{Binding Key}\" FontSize=\"15\" Padding=\"5\">\n                                        <ComboBoxItem>D1</ComboBoxItem>\n                                        <ComboBoxItem>D2</ComboBoxItem>\n                                        <ComboBoxItem>D3</ComboBoxItem>\n                                        <ComboBoxItem>D4</ComboBoxItem>\n                                        <ComboBoxItem>D5</ComboBoxItem>\n                                        <ComboBoxItem>D6</ComboBoxItem>\n                                        <ComboBoxItem>D7</ComboBoxItem>\n                                        <ComboBoxItem>D8</ComboBoxItem>\n                                        <ComboBoxItem>D9</ComboBoxItem>\n                                        <ComboBoxItem>D0</ComboBoxItem>\n                                        <ComboBoxItem>A</ComboBoxItem>\n                                        <ComboBoxItem>B</ComboBoxItem>\n                                        <ComboBoxItem>C</ComboBoxItem>\n                                        <ComboBoxItem>D</ComboBoxItem>\n                                        <ComboBoxItem>E</ComboBoxItem>\n                                        <ComboBoxItem>F</ComboBoxItem>\n                                        <ComboBoxItem>G</ComboBoxItem>\n                                        <ComboBoxItem>H</ComboBoxItem>\n                                        <ComboBoxItem>I</ComboBoxItem>\n                                        <ComboBoxItem>J</ComboBoxItem>\n                                        <ComboBoxItem>K</ComboBoxItem>\n                                        <ComboBoxItem>L</ComboBoxItem>\n                                        <ComboBoxItem>M</ComboBoxItem>\n                                        <ComboBoxItem>N</ComboBoxItem>\n                                        <ComboBoxItem>O</ComboBoxItem>\n                                        <ComboBoxItem>P</ComboBoxItem>\n                                        <ComboBoxItem>Q</ComboBoxItem>\n                                        <ComboBoxItem>R</ComboBoxItem>\n                                        <ComboBoxItem>S</ComboBoxItem>\n                                        <ComboBoxItem>T</ComboBoxItem>\n                                        <ComboBoxItem>U</ComboBoxItem>\n                                        <ComboBoxItem>V</ComboBoxItem>\n                                        <ComboBoxItem>W</ComboBoxItem>\n                                        <ComboBoxItem>X</ComboBoxItem>\n                                        <ComboBoxItem>Y</ComboBoxItem>\n                                        <ComboBoxItem>Z</ComboBoxItem>\n                                        <ComboBoxItem>NumPad1</ComboBoxItem>\n                                        <ComboBoxItem>NumPad2</ComboBoxItem>\n                                        <ComboBoxItem>NumPad3</ComboBoxItem>\n                                        <ComboBoxItem>NumPad4</ComboBoxItem>\n                                        <ComboBoxItem>NumPad5</ComboBoxItem>\n                                        <ComboBoxItem>NumPad6</ComboBoxItem>\n                                        <ComboBoxItem>NumPad7</ComboBoxItem>\n                                        <ComboBoxItem>NumPad8</ComboBoxItem>\n                                        <ComboBoxItem>NumPad9</ComboBoxItem>\n                                        <ComboBoxItem>NumPad0</ComboBoxItem>\n                                        <ComboBoxItem>F1</ComboBoxItem>\n                                        <ComboBoxItem>F2</ComboBoxItem>\n                                        <ComboBoxItem>F3</ComboBoxItem>\n                                        <ComboBoxItem>F4</ComboBoxItem>\n                                        <ComboBoxItem>F5</ComboBoxItem>\n                                        <ComboBoxItem>F6</ComboBoxItem>\n                                        <ComboBoxItem>F7</ComboBoxItem>\n                                        <ComboBoxItem>F8</ComboBoxItem>\n                                        <ComboBoxItem>F9</ComboBoxItem>\n                                        <ComboBoxItem>F10</ComboBoxItem>\n                                        <ComboBoxItem>F11</ComboBoxItem>\n                                        <ComboBoxItem>F12</ComboBoxItem>\n                                        <ComboBoxItem>Left</ComboBoxItem>\n                                        <ComboBoxItem>Right</ComboBoxItem>\n                                        <ComboBoxItem>Up</ComboBoxItem>\n                                        <ComboBoxItem>Down</ComboBoxItem>\n                                        <ComboBoxItem>Tab</ComboBoxItem>\n                                        <ComboBoxItem>Home</ComboBoxItem>\n                                        <ComboBoxItem>End</ComboBoxItem>\n                                        <ComboBoxItem>PageUp</ComboBoxItem>\n                                        <ComboBoxItem>PageDown</ComboBoxItem>\n                                    </ComboBox>\n                                </StackPanel>\n\n                                <Rectangle Height=\"1\" Margin=\"0,10,0,0\" Fill=\"{DynamicResource MaterialDesignDivider}\" />\n\n                                <StackPanel Orientation=\"Horizontal\" Margin=\"10\">\n                                    <TextBlock Text=\"{lex:Loc Page.Control.KB.Extra}\" Margin=\"0,0,10,0\" FontSize=\"20\" VerticalAlignment=\"Bottom\"></TextBlock>\n                                    <TextBox IsEnabled=\"False\" MinWidth=\"200\" Text=\"{Binding Extra, Mode=OneWay}\" FontSize=\"20\"></TextBox>\n                                </StackPanel>\n\n                                <Rectangle Height=\"1\" Margin=\"0,10\" Fill=\"{DynamicResource MaterialDesignDivider}\" />\n\n                                <StackPanel Orientation=\"Horizontal\" Margin=\"10\" HorizontalAlignment=\"Right\">\n                                    <materialDesign:Snackbar HorizontalAlignment=\"Right\" Margin=\"10\" x:Name=\"Snackbar\" MessageQueue=\"{materialDesign:MessageQueue}\" />\n                                    <Button Content=\"{lex:Loc Page.Control.KB.RegSave}\" Click=\"RegAndSave_OnClick\"></Button>\n                                    <Button Content=\"{lex:Loc Page.Control.KB.ClearSave}\" Click=\"ClearAndSave_OnClick\"></Button>\n                                </StackPanel>\n                            </StackPanel>\n                        </Border>\n                    </Grid>\n\n                </TabItem>\n                <TabItem>\n                    <TabItem.Header>\n                        <StackPanel Width=\"auto\" Height=\"auto\">\n                            <materialDesign:PackIcon\n                                Width=\"30\" Height=\"30\"\n                                HorizontalAlignment=\"Center\"\n                                Kind=\"Mouse\" />\n                            <TextBlock HorizontalAlignment=\"Center\" FontSize=\"13\" Text=\"{lex:Loc Page.Control.Mouse}\" />\n                        </StackPanel>\n                    </TabItem.Header>\n                    <StackPanel>\n\n                        <TextBlock FontSize=\"25\" Margin=\"10\" Text=\"{lex:Loc Page.Control.MouseAction.OnDesktop}\"></TextBlock>\n\n                        <Grid x:Name=\"DesktopMouseActionBox\">\n                            <Grid.RowDefinitions>\n                                <RowDefinition Height=\"Auto\"></RowDefinition>\n                                <RowDefinition Height=\"Auto\"></RowDefinition>\n                            </Grid.RowDefinitions>\n                            <Grid.ColumnDefinitions>\n                                <ColumnDefinition Width=\"Auto\"></ColumnDefinition>\n                                <ColumnDefinition Width=\"*\"></ColumnDefinition>\n                            </Grid.ColumnDefinitions>\n\n                            <StackPanel Orientation=\"Horizontal\" Margin=\"10\" Grid.Row=\"0\" Grid.Column=\"0\">\n                                <StackPanel.Resources>\n\n                                </StackPanel.Resources>\n                                <UniformGrid Columns=\"4\">\n                                    <CheckBox IsChecked=\"{Binding LWin}\">LWin</CheckBox>\n                                    <CheckBox IsChecked=\"{Binding Ctrl}\">Ctrl</CheckBox>\n                                    <CheckBox IsChecked=\"{Binding Alt}\">Alt</CheckBox>\n                                    <CheckBox IsChecked=\"{Binding Shift}\">Shift</CheckBox>\n                                </UniformGrid>\n                                <ComboBox MinWidth=\"100\"\n                                          Style=\"{StaticResource MaterialDesignOutlinedComboBox}\"\n                                          ItemsSource=\"{Binding MouseButtons}\"\n                                          SelectedValuePath=\"Value\"\n                                          SelectedValue=\"{Binding MouseButton}\" FontSize=\"15\" Padding=\"5\">\n                                    <ComboBox.ItemTemplate>\n                                        <DataTemplate>\n                                            <TextBlock\n                                                Text=\"{lex:Loc {Binding Value,Mode=OneWay,\n                                                Converter={StaticResource LocConverter},ConverterParameter=Page.Control.MouseButtons.}}\" />\n                                        </DataTemplate>\n                                    </ComboBox.ItemTemplate>\n                                </ComboBox>\n                            </StackPanel>\n\n                            <StackPanel Orientation=\"Horizontal\" Grid.Row=\"0\" Grid.Column=\"1\" HorizontalAlignment=\"Left\">\n                                <TextBlock FontSize=\"30\" Margin=\"0,8,10,10\" Text=\"{lex:Loc Page.Control.MouseAction.Behavior}\"></TextBlock>\n                                <ComboBox MinWidth=\"200\" Width=\"400\" x:Name=\"cbbDesktopActions\"\n                                          Style=\"{StaticResource MaterialDesignOutlinedComboBox}\"\n                                          ItemsSource=\"{Binding DesktopActions}\"\n                                          SelectedValuePath=\"Value\"\n                                          FontSize=\"15\" Padding=\"5\">\n                                    <ComboBox.ItemTemplate>\n                                        <DataTemplate>\n                                            <TextBlock\n                                                Text=\"{lex:Loc {Binding Value,Mode=OneWay,\n                                                Converter={StaticResource LocConverter},ConverterParameter=Mouse.Action.}}\" />\n                                        </DataTemplate>\n                                    </ComboBox.ItemTemplate>\n                                    <ComboBox.SelectedValue>\n                                        <MultiBinding Converter=\"{StaticResource MouseActionConverter}\" Mode=\"OneWay\">\n                                            <Binding Path=\".\" Source=\"{StaticResource madp}\"></Binding>\n                                            <Binding Path=\"LWin\"></Binding>\n                                            <Binding Path=\"Ctrl\"></Binding>\n                                            <Binding Path=\"Alt\"></Binding>\n                                            <Binding Path=\"Shift\"></Binding>\n                                            <Binding Path=\"MouseButton\"></Binding>\n                                        </MultiBinding>\n                                    </ComboBox.SelectedValue>\n                                </ComboBox>\n                                <Button Content=\"{lex:Loc Page.Control.MouseAction.Bind}\" Click=\"DesktopActionBind_OnClick\"></Button>\n                            </StackPanel>\n                            <!-- <Expander Grid.Row=\"1\" Grid.Column=\"0\" Grid.ColumnSpan=\"2\" -->\n                            <!--           HorizontalAlignment=\"Stretch\" materialDesign:ExpanderAssist.HorizontalHeaderPadding=\"10 0\" -->\n                            <!--           Header=\"{lex:Loc Page.Control.MouseAction.ExpanderHeader}\"> -->\n                            <!--     <StackPanel Orientation=\"Vertical\" TextBlock.Foreground=\"{DynamicResource MaterialDesignBody}\" Margin=\"10\"> -->\n                            <!--         <TextBlock Text=\"{lex:Loc Page.Control.MouseAction.DesktopBindings}\" /> -->\n                            <!--     </StackPanel> -->\n                            <!-- </Expander> -->\n                        </Grid>\n\n                        <Rectangle Height=\"1\" Margin=\"0,10\" Fill=\"{DynamicResource MaterialDesignDivider}\" />\n\n                        <TextBlock FontSize=\"25\" Margin=\"10\" Text=\"{lex:Loc Page.Control.MouseAction.OnThumb}\"></TextBlock>\n\n                        <Grid x:Name=\"WindowMouseActionBox\">\n                            <Grid.RowDefinitions>\n                                <RowDefinition Height=\"Auto\"></RowDefinition>\n                                <RowDefinition Height=\"Auto\"></RowDefinition>\n                            </Grid.RowDefinitions>\n                            <Grid.ColumnDefinitions>\n                                <ColumnDefinition Width=\"Auto\"></ColumnDefinition>\n                                <ColumnDefinition Width=\"*\"></ColumnDefinition>\n                            </Grid.ColumnDefinitions>\n                            <StackPanel Orientation=\"Horizontal\" Margin=\"10\" Grid.Row=\"0\" Grid.Column=\"0\">\n\n                                <UniformGrid Columns=\"4\">\n                                    <CheckBox IsChecked=\"{Binding LWin}\">LWin</CheckBox>\n                                    <CheckBox IsChecked=\"{Binding Ctrl}\">Ctrl</CheckBox>\n                                    <CheckBox IsChecked=\"{Binding Alt}\">Alt</CheckBox>\n                                    <CheckBox IsChecked=\"{Binding Shift}\">Shift</CheckBox>\n                                </UniformGrid>\n\n                                <ComboBox MinWidth=\"100\"\n                                          Style=\"{StaticResource MaterialDesignOutlinedComboBox}\"\n                                          ItemsSource=\"{Binding MouseButtons}\"\n                                          SelectedValuePath=\"Value\"\n                                          SelectedValue=\"{Binding MouseButton}\" FontSize=\"15\" Padding=\"5\">\n                                    <ComboBox.ItemTemplate>\n                                        <DataTemplate>\n                                            <TextBlock\n                                                Text=\"{lex:Loc {Binding Value,Mode=OneWay,\n                                                Converter={StaticResource LocConverter},ConverterParameter=Page.Control.MouseButtons.}}\" />\n                                        </DataTemplate>\n                                    </ComboBox.ItemTemplate>\n                                </ComboBox>\n                            </StackPanel>\n                            <StackPanel Orientation=\"Horizontal\" Grid.Row=\"0\" Grid.Column=\"1\" HorizontalAlignment=\"Left\">\n                                <TextBlock FontSize=\"30\" Margin=\"0,8,10,10\" Text=\"{lex:Loc Page.Control.MouseAction.Behavior}\"></TextBlock>\n                                <ComboBox MinWidth=\"200\" Width=\"400\" x:Name=\"cbbWindowActions\"\n                                          Style=\"{StaticResource MaterialDesignOutlinedComboBox}\"\n                                          ItemsSource=\"{Binding WindowActions}\"\n                                          SelectedValuePath=\"Value\"\n                                          FontSize=\"15\" Padding=\"5\">\n                                    <ComboBox.ItemTemplate>\n                                        <DataTemplate>\n                                            <TextBlock\n                                                Text=\"{lex:Loc {Binding Value,Mode=OneWay,\n                                                Converter={StaticResource LocConverter},ConverterParameter=Mouse.Action.}}\" />\n                                        </DataTemplate>\n                                    </ComboBox.ItemTemplate>\n                                    <ComboBox.SelectedValue>\n                                        <MultiBinding Converter=\"{StaticResource MouseActionConverter}\" Mode=\"OneWay\">\n                                            <Binding Path=\".\" Source=\"{StaticResource mawp}\"></Binding>\n                                            <Binding Path=\"LWin\"></Binding>\n                                            <Binding Path=\"Ctrl\"></Binding>\n                                            <Binding Path=\"Alt\"></Binding>\n                                            <Binding Path=\"Shift\"></Binding>\n                                            <Binding Path=\"MouseButton\"></Binding>\n                                        </MultiBinding>\n                                    </ComboBox.SelectedValue>\n                                </ComboBox>\n                                <Button Content=\"{lex:Loc Page.Control.MouseAction.Bind}\" Click=\"WindowActionBind_OnClick\"></Button>\n                            </StackPanel>\n                            <!-- <Expander Grid.Row=\"1\" Grid.Column=\"0\" Grid.ColumnSpan=\"2\" -->\n                            <!--           HorizontalAlignment=\"Stretch\" materialDesign:ExpanderAssist.HorizontalHeaderPadding=\"10 0\" -->\n                            <!--           Header=\"{lex:Loc Page.Control.MouseAction.ExpanderHeader}\"> -->\n                            <!--     <StackPanel Orientation=\"Vertical\" TextBlock.Foreground=\"{DynamicResource MaterialDesignBody}\" Margin=\"10\"> -->\n                            <!--         <TextBlock Text=\"{lex:Loc Page.Control.MouseAction.WindowBindings}\" /> -->\n                            <!--     </StackPanel> -->\n                            <!-- </Expander> -->\n                        </Grid>\n\n                        <Rectangle Height=\"1\" Margin=\"0,10\" Fill=\"{DynamicResource MaterialDesignDivider}\" />\n\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock Margin=\"10\" FontSize=\"25\" Text=\"{lex:Loc Page.Control.Mouse.UseWheelSwitchDesktopWhenOnTaskbar}\"></TextBlock>\n                            <ToggleButton x:Name=\"UseWheelSwitchDesktopWhenOnTaskbar\"\n                                          Style=\"{StaticResource MaterialDesignSwitchToggleButton}\"\n                                          Width=\"50\" Margin=\"5,5\"\n                                          IsChecked=\"{Binding Path=UseWheelSwitchDesktopWhenOnTaskbar, Mode=TwoWay}\" />\n                        </StackPanel>\n\n                        <UniformGrid Rows=\"2\" Columns=\"2\" Width=\"500\" MinWidth=\"500\" HorizontalAlignment=\"Left\">\n                            <TextBlock Margin=\"10,5\" Text=\"{lex:Loc Page.Control.Mouse.Wheel.Up}\"></TextBlock>\n                            <TextBlock Margin=\"10,5\" Text=\"{lex:Loc Page.Control.Mouse.Wheel.Down}\"></TextBlock>\n                            <TextBlock Margin=\"10,5\" Text=\"{lex:Loc Page.Control.Mouse.Wheel.SUp}\"></TextBlock>\n                            <TextBlock Margin=\"10,5\" Text=\"{lex:Loc Page.Control.Mouse.Wheel.SDown}\"></TextBlock>\n                        </UniformGrid>\n\n                    </StackPanel>\n\n                </TabItem>\n            </TabControl>\n        </materialDesign:Card>\n    </Grid>\n\n</UserControl>"
  },
  {
    "path": "WPF/ControlPanel/Pages/Control.xaml.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Text.RegularExpressions;\nusing System.Windows.Controls;\nusing ControlPanel.ViewModels;\nusing MaterialDesignThemes.Wpf;\nusing VirtualSpace;\n\nnamespace ControlPanel.Pages;\n\npublic partial class Control\n{\n    private static Control? _instance;\n\n    public Control()\n    {\n        InitializeComponent();\n    }\n\n    private Control( string headerKey, PackIconKind iconKind ) : this()\n    {\n        var mdc = (MenuContainerViewModel)MenuContainer.DataContext;\n        mdc.HeaderKey = headerKey;\n        mdc.IconKind = iconKind;\n\n        KeyBindingBox.DataContext = new KeyBindingModel();\n        DesktopMouseActionBox.DataContext = new MouseActionModel();\n        WindowMouseActionBox.DataContext = new MouseActionModel();\n        UseWheelSwitchDesktopWhenOnTaskbar.DataContext = WindowMouseActionBox.DataContext;\n\n        LoadKeyboardTreeView();\n\n        SettingsViewModel.LanguageChanged -= SettingsOnLanguageChanged;\n        SettingsViewModel.LanguageChanged += SettingsOnLanguageChanged;\n    }\n\n    private void SettingsOnLanguageChanged( object? sender, EventArgs e )\n    {\n        foreach ( var item in KeyboardTreeView.Items )\n        {\n            var node = item as TreeViewItem;\n            if ( node is null ) continue;\n\n            var tag = node.Tag;\n            node.Header = Agent.Langs.GetString( tag is null ? node.Name : tag.ToString() );\n\n            VisitTreeViewItem( node );\n        }\n    }\n\n    private static void VisitTreeViewItem( TreeViewItem item )\n    {\n        foreach ( var child in item.Items )\n        {\n            if ( child is not TreeViewItem childItem ) continue;\n\n            var tag = childItem.Tag;\n            if ( tag is null )\n            {\n                childItem.Header = Agent.Langs.GetString( childItem.Name );\n            }\n            else\n            {\n                var currentHeader = childItem.Header.ToString();\n                var m             = Regex.Match( currentHeader, @\"[^\\d]+(\\d+)$\" );\n                if ( m.Success )\n                {\n                    var index = m.Groups[1].Value;\n                    childItem.Header = Agent.Langs.GetString( tag.ToString() ) + index;\n                }\n                else\n                {\n                    childItem.Header = Agent.Langs.GetString( tag.ToString() );\n                }\n            }\n\n            if ( childItem.Items.Count > 0 )\n                VisitTreeViewItem( childItem );\n        }\n    }\n\n    public static Control Create( string headerKey, PackIconKind iconKind )\n    {\n        return _instance ??= new Control( headerKey, iconKind );\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Pages/Dialogs/ProfileNameDialog.xaml",
    "content": "﻿<UserControl x:Class=\"ControlPanel.Pages.Dialogs.ProfileNameDialog\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n             xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n             xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n             xmlns:wpf=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n             xmlns:system=\"clr-namespace:System;assembly=System.Runtime\"\n             xmlns:lex=\"http://wpflocalizeextension.codeplex.com\"\n             mc:Ignorable=\"d\"\n             d:DesignHeight=\"300\" d:DesignWidth=\"300\">\n    \n    <StackPanel>\n        <TextBox Text=\"{Binding EditProfileName, UpdateSourceTrigger=PropertyChanged}\" Margin=\"10\" FontSize=\"20\" MinWidth=\"300\"></TextBox>\n\n        <TextBlock x:Name=\"ErrorBox\" Visibility=\"Collapsed\" Foreground=\"Red\" Margin=\"10\" FontSize=\"15\"></TextBlock>\n\n        <StackPanel HorizontalAlignment=\"Center\" Orientation=\"Horizontal\">\n            <Button Margin=\"10\" Command=\"{x:Static wpf:DialogHost.CloseDialogCommand}\"\n                    IsDefault=\"True\" Content=\"{lex:Loc Dialogs.OK}\"\n                    Style=\"{StaticResource MaterialDesignFlatButton}\">\n                <Button.CommandParameter>\n                    <system:Boolean>True</system:Boolean>\n                </Button.CommandParameter>\n            </Button>\n            <Button Margin=\"10\" Command=\"{x:Static wpf:DialogHost.CloseDialogCommand}\"\n                    IsCancel=\"True\" Content=\"{lex:Loc Dialogs.Cancel}\"\n                    Style=\"{StaticResource MaterialDesignFlatButton}\">\n                <Button.CommandParameter>\n                    <system:Boolean>False</system:Boolean>\n                </Button.CommandParameter>\n            </Button>\n        </StackPanel>\n    </StackPanel>\n\n</UserControl>"
  },
  {
    "path": "WPF/ControlPanel/Pages/Dialogs/ProfileNameDialog.xaml.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.Windows;\nusing System.Windows.Controls;\n\nnamespace ControlPanel.Pages.Dialogs;\n\npublic partial class ProfileNameDialog : UserControl\n{\n    public ProfileNameDialog()\n    {\n        InitializeComponent();\n        DataContext = this;\n    }\n\n    public ProfileNameDialog( string profileName ) : this()\n    {\n        EditProfileName = profileName;\n    }\n\n    public string EditProfileName { get; set; }\n\n    public void SetErrors( string errors )\n    {\n        ErrorBox.Text = errors;\n        ErrorBox.Visibility = Visibility.Visible;\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Pages/Dialogs/YesNoWithNote.xaml",
    "content": "﻿<UserControl x:Class=\"ControlPanel.Pages.Dialogs.YesNoWithNote\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n             xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n             xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n             xmlns:wpf=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n             xmlns:lex=\"http://wpflocalizeextension.codeplex.com\"\n             xmlns:system=\"clr-namespace:System;assembly=System.Runtime\"\n             mc:Ignorable=\"d\"\n             d:DesignHeight=\"300\" d:DesignWidth=\"300\">\n    \n    <StackPanel>\n        <DockPanel VerticalAlignment=\"Center\">\n            <wpf:PackIcon DockPanel.Dock=\"Left\" Kind=\"{Binding Icon}\" Width=\"30\" Height=\"30\" Margin=\"20,30,10,30\"></wpf:PackIcon>\n            <TextBlock Text=\"{Binding Notes}\" FontSize=\"20\" Margin=\"10,0\" VerticalAlignment=\"Center\"></TextBlock>\n        </DockPanel>\n\n        <StackPanel HorizontalAlignment=\"Center\" Orientation=\"Horizontal\">\n            <Button Margin=\"10\" Command=\"{x:Static wpf:DialogHost.CloseDialogCommand}\"\n                    IsDefault=\"True\" Content=\"{lex:Loc Dialogs.OK}\"\n                    Style=\"{StaticResource MaterialDesignFlatButton}\">\n                <Button.CommandParameter>\n                    <system:Boolean>True</system:Boolean>\n                </Button.CommandParameter>\n            </Button>\n            <Button Margin=\"10\" Command=\"{x:Static wpf:DialogHost.CloseDialogCommand}\"\n                    IsCancel=\"True\" Content=\"{lex:Loc Dialogs.Cancel}\"\n                    Style=\"{StaticResource MaterialDesignFlatButton}\">\n                <Button.CommandParameter>\n                    <system:Boolean>False</system:Boolean>\n                </Button.CommandParameter>\n            </Button>\n        </StackPanel>\n    </StackPanel>\n\n</UserControl>"
  },
  {
    "path": "WPF/ControlPanel/Pages/Dialogs/YesNoWithNote.xaml.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.Windows.Controls;\nusing MaterialDesignThemes.Wpf;\n\nnamespace ControlPanel.Pages.Dialogs;\n\npublic partial class YesNoWithNote : UserControl\n{\n    public YesNoWithNote()\n    {\n        InitializeComponent();\n    }\n\n    public YesNoWithNote( string notes, PackIconKind? iconKind = null ) : this()\n    {\n        DataContext = this;\n        Notes = notes;\n        Icon = iconKind ?? PackIconKind.Info;\n    }\n\n    public string       Notes { get; set; } = string.Empty;\n    public PackIconKind Icon  { get; set; }\n}"
  },
  {
    "path": "WPF/ControlPanel/Pages/General.xaml",
    "content": "﻿<UserControl x:Class=\"ControlPanel.Pages.General\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n             xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n             xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n             xmlns:commons=\"clr-namespace:ControlPanel.Pages.Menus.Commons\"\n             xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n             xmlns:lex=\"http://wpflocalizeextension.codeplex.com\"\n             xmlns:converters=\"clr-namespace:ControlPanel.Converters\"\n             mc:Ignorable=\"d\">\n    <UserControl.Resources>\n        <converters:LocConverter x:Key=\"LocConverter\" />\n        <converters:CheckBoxConverter x:Key=\"CheckBoxConverter\" />\n    </UserControl.Resources>\n\n    <materialDesign:DialogHost Identifier=\"GeneralDialog\">\n        <Grid>\n            <Grid.RowDefinitions>\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"*\" />\n            </Grid.RowDefinitions>\n\n            <commons:MenuContainer x:Name=\"MenuContainer\" Grid.Row=\"0\" />\n\n            <materialDesign:Card Grid.Row=\"1\" materialDesign:ElevationAssist.Elevation=\"Dp2\" Margin=\"10,10,10,12\">\n                <materialDesign:Card.Resources>\n                    <Style TargetType=\"TextBlock\">\n                        <Setter Property=\"Margin\" Value=\"10\"></Setter>\n                    </Style>\n                </materialDesign:Card.Resources>\n\n                <StackPanel>\n                    <TextBlock Text=\"{lex:Loc Page.General.Basics}\" FontSize=\"20\"></TextBlock>\n                    <Grid Margin=\"30,0\">\n                        <Grid.RowDefinitions>\n                            <RowDefinition Height=\"Auto\"></RowDefinition>\n                            <RowDefinition Height=\"Auto\"></RowDefinition>\n                        </Grid.RowDefinitions>\n                        <CheckBox Content=\"{lex:Loc Page.General.RunOnStartup}\"\n                                  IsChecked=\"{Binding RunOnStartup}\">\n                        </CheckBox>\n                        <StackPanel Grid.Row=\"1\" Orientation=\"Horizontal\" Margin=\"12,-10\">\n                            <TextBlock Text=\"{lex:Loc Note.General.Label.TaskScheduler}\" VerticalAlignment=\"Center\"></TextBlock>\n                            <TextBlock VerticalAlignment=\"Center\">\n                                <Hyperlink TextDecorations=\"None\" Click=\"OpenTaskScheduler_OnClick\">\n                                    <TextBlock Text=\"{lex:Loc Page.General.TaskScheduler}\"></TextBlock>\n                                </Hyperlink>\n                            </TextBlock>\n                        </StackPanel>\n                    </Grid>\n\n                    <Rectangle Height=\"1\" Margin=\"0,10,0,0\" Fill=\"{DynamicResource MaterialDesignDivider}\" />\n\n                    <TextBlock Text=\"{lex:Loc Page.General.Navigation}\" FontSize=\"20\"></TextBlock>\n                    <Grid Margin=\"30,0\">\n                        <Grid.RowDefinitions>\n                            <RowDefinition Height=\"Auto\"></RowDefinition>\n                            <RowDefinition Height=\"Auto\"></RowDefinition>\n                        </Grid.RowDefinitions>\n                        <StackPanel Orientation=\"Horizontal\">\n                            <Grid>\n                                <Grid.ColumnDefinitions>\n                                    <ColumnDefinition Width=\"Auto\"></ColumnDefinition>\n                                    <ColumnDefinition></ColumnDefinition>\n                                </Grid.ColumnDefinitions>\n                                <CheckBox x:Name=\"chbNavH\" Content=\"{lex:Loc Page.General.Nav.H}\" Width=\"400\"\n                                          IsChecked=\"{Binding NavH}\">\n                                </CheckBox>\n                                <StackPanel Orientation=\"Horizontal\" Grid.Column=\"1\">\n                                    <TextBlock Text=\"{lex:Loc Page.General.Nav.HType}\" Margin=\"5,5,5,0\"></TextBlock>\n                                    <ComboBox IsEnabled=\"{Binding ElementName=chbNavH, Path=IsChecked}\"\n                                              ItemsSource=\"{Binding NavHTypeList}\"\n                                              SelectedValuePath=\"Value\"\n                                              SelectedValue=\"{Binding NavHType}\">\n                                        <ComboBox.ItemTemplate>\n                                            <DataTemplate>\n                                                <TextBlock\n                                                    Text=\"{lex:Loc {Binding Value,Mode=OneWay,\n                                                Converter={StaticResource LocConverter},ConverterParameter=Page.General.Nav.HType.}}\" />\n                                            </DataTemplate>\n                                        </ComboBox.ItemTemplate>\n                                    </ComboBox>\n                                </StackPanel>\n                            </Grid>\n                        </StackPanel>\n\n                        <CheckBox Grid.Row=\"1\" Content=\"{lex:Loc Page.General.Nav.V}\" Margin=\"0,10,0,0\"\n                                  IsChecked=\"{Binding NavV}\">\n                        </CheckBox>\n                    </Grid>\n\n                    <Rectangle Height=\"1\" Margin=\"0,10,0,0\" Fill=\"{DynamicResource MaterialDesignDivider}\" />\n\n                    <TextBlock Text=\"{lex:Loc Page.General.Cluster}\" FontSize=\"20\"></TextBlock>\n                    <Grid Margin=\"30,0\">\n                        <Grid.RowDefinitions>\n                            <RowDefinition Height=\"Auto\"></RowDefinition>\n                            <RowDefinition Height=\"Auto\"></RowDefinition>\n                            <RowDefinition Height=\"Auto\"></RowDefinition>\n                            <RowDefinition Height=\"Auto\"></RowDefinition>\n                            <RowDefinition Height=\"Auto\"></RowDefinition>\n                        </Grid.RowDefinitions>\n                        <CheckBox Content=\"{lex:Loc Page.General.HideMainViewIfItsShown}\"\n                                  IsChecked=\"{Binding Path=Cluster.HideMainViewIfItsShown}\">\n                        </CheckBox>\n                        <CheckBox Grid.Row=\"1\" Margin=\"0,10,0,0\"\n                                  IsChecked=\"{Binding Path=Cluster.NotificationOnVdChanged}\"\n                                  Content=\"{lex:Loc Page.General.NotificationOnVdChanged}\">\n                        </CheckBox>\n                        <Grid Grid.Row=\"2\" Margin=\"0,10,0,0\">\n                            <Grid.ColumnDefinitions>\n                                <ColumnDefinition Width=\"Auto\"></ColumnDefinition>\n                                <ColumnDefinition></ColumnDefinition>\n                            </Grid.ColumnDefinitions>\n                            <CheckBox x:Name=\"chbShowVDIndexOnTrayIcon\" Width=\"400\"\n                                      Content=\"{lex:Loc Page.General.ShowVDIndexOnTrayIcon}\"\n                                      IsChecked=\"{Binding Path=Cluster.ShowVDIndexOnTrayIcon}\">\n                            </CheckBox>\n                            <StackPanel Orientation=\"Horizontal\" Grid.Column=\"1\">\n                                <RadioButton Margin=\"0,0,20,0\" Content=\"{lex:Loc Page.General.StyleOfVDIndexOnTrayIcon.0}\"\n                                             IsEnabled=\"{Binding ElementName=chbShowVDIndexOnTrayIcon, Path=IsChecked}\"\n                                             IsChecked=\"{Binding Path=Cluster.StyleOfVDIndexOnTrayIcon, Converter={StaticResource CheckBoxConverter},ConverterParameter=0}\">\n                                </RadioButton>\n                                <RadioButton Margin=\"0,0,20,0\" Content=\"{lex:Loc Page.General.StyleOfVDIndexOnTrayIcon.1}\"\n                                             IsEnabled=\"{Binding ElementName=chbShowVDIndexOnTrayIcon, Path=IsChecked}\"\n                                             IsChecked=\"{Binding Path=Cluster.StyleOfVDIndexOnTrayIcon, Converter={StaticResource CheckBoxConverter},ConverterParameter=1}\">\n                                </RadioButton>\n                                <RadioButton Margin=\"0,0,20,0\" Content=\"{lex:Loc Page.General.StyleOfVDIndexOnTrayIcon.2}\"\n                                             IsEnabled=\"{Binding ElementName=chbShowVDIndexOnTrayIcon, Path=IsChecked}\"\n                                             IsChecked=\"{Binding Path=Cluster.StyleOfVDIndexOnTrayIcon, Converter={StaticResource CheckBoxConverter},ConverterParameter=2}\">\n                                </RadioButton>\n                            </StackPanel>\n                        </Grid>\n\n                        <CheckBox Grid.Row=\"3\" Margin=\"0,10,0,0\"\n                                  Content=\"{lex:Loc Page.General.HideOnStart}\"\n                                  IsChecked=\"{Binding Path=Cluster.HideOnStart}\">\n                        </CheckBox>\n                        <CheckBox Grid.Row=\"4\" Margin=\"0,10,0,0\"\n                                  Content=\"{lex:Loc Page.General.EnableWindowFilter}\"\n                                  IsChecked=\"{Binding Path=Cluster.EnableWindowFilter}\">\n                        </CheckBox>\n                    </Grid>\n                </StackPanel>\n\n            </materialDesign:Card>\n        </Grid>\n    </materialDesign:DialogHost>\n\n</UserControl>"
  },
  {
    "path": "WPF/ControlPanel/Pages/General.xaml.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System.Windows;\nusing ControlPanel.ViewModels;\nusing MaterialDesignThemes.Wpf;\nusing VirtualSpace.Helpers;\n\nnamespace ControlPanel.Pages;\n\npublic partial class General\n{\n    private static General?         _instance;\n    private static GeneralViewModel _vm;\n\n    public General()\n    {\n        InitializeComponent();\n    }\n\n    private General( string headerKey, PackIconKind iconKind ) : this()\n    {\n        var mdc = (MenuContainerViewModel)MenuContainer.DataContext;\n        mdc.HeaderKey = headerKey;\n        mdc.IconKind = iconKind;\n        _vm = new GeneralViewModel();\n        DataContext = _vm;\n    }\n\n    public static General Create( string headerKey, PackIconKind iconKind )\n    {\n        return _instance ??= new General( headerKey, iconKind );\n    }\n\n    private void OpenTaskScheduler_OnClick( object sender, RoutedEventArgs e )\n    {\n        TaskSchedulerHelper.OpenWinTaskScheduler();\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Pages/Help.xaml",
    "content": "﻿<UserControl x:Class=\"ControlPanel.Pages.Help\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n             xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n             xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n             mc:Ignorable=\"d\"\n             d:DesignHeight=\"760\" d:DesignWidth=\"1024\">\n\n    <Grid Margin=\"10\">\n        <Grid.RowDefinitions>\n            <RowDefinition Height=\"Auto\"></RowDefinition>\n            <RowDefinition Height=\"Auto\"></RowDefinition>\n            <RowDefinition Height=\"Auto\"></RowDefinition>\n        </Grid.RowDefinitions>\n        <StackPanel Orientation=\"Horizontal\">\n            <Image Source=\"../Resources/Images/AboutLogo_2.png\" Width=\"128\" Height=\"128\"></Image>\n            <TextBlock FontSize=\"100\" Margin=\"20,0\" x:Name=\"lb_AppName\"></TextBlock>\n        </StackPanel>\n        <Grid Grid.Row=\"1\" Margin=\"0 10\">\n            <Grid.RowDefinitions>\n                <RowDefinition Height=\"Auto\"></RowDefinition>\n                <RowDefinition Height=\"Auto\"></RowDefinition>\n                <RowDefinition Height=\"Auto\"></RowDefinition>\n            </Grid.RowDefinitions>\n            <Grid.ColumnDefinitions>\n                <ColumnDefinition Width=\"100\"></ColumnDefinition>\n                <ColumnDefinition Width=\"Auto\"></ColumnDefinition>\n            </Grid.ColumnDefinitions>\n            <TextBlock>Version</TextBlock><TextBlock Grid.Row=\"0\" Grid.Column=\"1\" x:Name=\"lb_Version\"></TextBlock>\n            <TextBlock Grid.Row=\"1\" Grid.Column=\"0\">Copyright</TextBlock><TextBlock Grid.Row=\"1\" Grid.Column=\"1\" x:Name=\"lb_Copyright\"></TextBlock>\n            <TextBlock Grid.Row=\"2\" Grid.Column=\"0\"></TextBlock>\n            <TextBlock Grid.Row=\"2\" Grid.Column=\"1\">\n                <Hyperlink Click=\"Hyperlink_OnClick\" x:Name=\"llb_CompanyUri\">\n                    <Run x:Name=\"llb_CompanyText\"></Run>\n                </Hyperlink>\n            </TextBlock>\n        </Grid>\n        <Border Grid.Row=\"2\" Grid.Column=\"0\" HorizontalAlignment=\"Left\"\n                BorderThickness=\"1\" Margin=\"0 10\" BorderBrush=\"DarkGray\">\n            <ListBox x:Name=\"lbox_Env\" Height=\"200\" Width=\"700\"></ListBox>\n        </Border>\n\n    </Grid>\n</UserControl>"
  },
  {
    "path": "WPF/ControlPanel/Pages/Help.xaml.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Diagnostics;\nusing System.Reflection;\nusing System.Runtime.InteropServices;\nusing System.Windows;\nusing System.Windows.Controls;\nusing System.Windows.Documents;\n\nnamespace ControlPanel.Pages;\n\npublic partial class Help : UserControl\n{\n    private static Help? _instance = null;\n\n    private Help()\n    {\n        InitializeComponent();\n        AppInfo();\n    }\n\n    public static Help Instance => _instance ??= new Help();\n\n    private void Hyperlink_OnClick( object sender, RoutedEventArgs e )\n    {\n        var hl  = (Hyperlink)sender;\n        var url = hl.NavigateUri.ToString();\n\n        var psi = new ProcessStartInfo\n        {\n            FileName = url,\n            UseShellExecute = true\n        };\n        Process.Start( psi );\n    }\n\n    private void AppInfo()\n    {\n        var entryAssembly = Assembly.GetEntryAssembly();\n        try\n        {\n            lb_AppName.Text = ( (AssemblyProductAttribute)Attribute.GetCustomAttribute(\n                entryAssembly,\n                typeof( AssemblyProductAttribute ),\n                false ) ).Product;\n\n            lb_Version.Text = ( (AssemblyInformationalVersionAttribute)Attribute.GetCustomAttribute(\n                entryAssembly,\n                typeof( AssemblyInformationalVersionAttribute ),\n                false ) ).InformationalVersion;\n\n            lb_Copyright.Text = ( (AssemblyCopyrightAttribute)Attribute.GetCustomAttribute(\n                entryAssembly,\n                typeof( AssemblyCopyrightAttribute ),\n                false ) ).Copyright;\n\n            llb_CompanyUri.NavigateUri = new Uri( ( (AssemblyCompanyAttribute)Attribute.GetCustomAttribute(\n                entryAssembly,\n                typeof( AssemblyCompanyAttribute ),\n                false ) ).Company );\n            llb_CompanyText.Text = llb_CompanyUri.NavigateUri.ToString();\n        }\n        catch\n        {\n            // ignored\n        }\n\n        if ( lbox_Env.Items.Count == 0 )\n            lbox_Env.Items.Add( RuntimeInformation.FrameworkDescription );\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Pages/Logs.xaml",
    "content": "﻿<UserControl x:Class=\"ControlPanel.Pages.Logs\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n             xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n             xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n             xmlns:lex=\"http://wpflocalizeextension.codeplex.com\"\n             xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n             xmlns:cp=\"clr-namespace:ControlPanel.Pages\"\n             xmlns:cMenus=\"clr-namespace:ControlPanel.Pages.Menus.Commons\"\n             mc:Ignorable=\"d\">\n\n    <UserControl.Resources>\n        <ResourceDictionary>\n            <ContextMenu x:Key=\"ctx\">\n                <MenuItem Header=\"{lex:Loc logTab.Menu.Clear}\" Click=\"Clear_Click\" CommandParameter=\"{Binding RelativeSource={RelativeSource Self}, Path=Parent}\" />\n            </ContextMenu>\n            <Style TargetType=\"ScrollViewer\">\n                <Setter Property=\"Margin\" Value=\"5\" />\n            </Style>\n        </ResourceDictionary>\n    </UserControl.Resources>\n\n    <Grid>\n        <Grid.RowDefinitions>\n            <RowDefinition Height=\"Auto\" />\n            <RowDefinition Height=\"*\" />\n        </Grid.RowDefinitions>\n\n        <cMenus:MenuContainer x:Name=\"MenuContainer\" Grid.Row=\"0\" />\n\n        <materialDesign:Card Grid.Row=\"1\" materialDesign:ElevationAssist.Elevation=\"Dp2\" Margin=\"10,10,10,12\">\n            <TabControl x:Name=\"TcLogs\" ContextMenuOpening=\"TabItem_OnContextMenuOpening\">\n                <TabItem Header=\"{lex:Loc logTabInfo}\" ContextMenu=\"{StaticResource ctx}\">\n                    <ScrollViewer>\n                        <Run Text=\"{Binding Path=(cp:Logs.TbInfo)}\" />\n                    </ScrollViewer>\n                </TabItem>\n                <TabItem Header=\"{lex:Loc logTabDebug}\" ContextMenu=\"{StaticResource ctx}\">\n                    <ScrollViewer>\n                        <Run Text=\"{Binding Path=(cp:Logs.TbDebug)}\" />\n                    </ScrollViewer>\n                </TabItem>\n                <TabItem Header=\"{lex:Loc logTabVerbose}\" ContextMenu=\"{StaticResource ctx}\">\n                    <ScrollViewer>\n                        <Run Text=\"{Binding Path=(cp:Logs.TbVerbose)}\" />\n                    </ScrollViewer>\n                </TabItem>\n                <TabItem Header=\"{lex:Loc logTabEvent}\" ContextMenu=\"{StaticResource ctx}\">\n                    <ScrollViewer>\n                        <Run Text=\"{Binding Path=(cp:Logs.TbEvent)}\" />\n                    </ScrollViewer>\n                </TabItem>\n                <TabItem Header=\"{lex:Loc logTabWarning}\" ContextMenu=\"{StaticResource ctx}\">\n                    <ScrollViewer>\n                        <Run Text=\"{Binding Path=(cp:Logs.TbWarning)}\" />\n                    </ScrollViewer>\n                </TabItem>\n                <TabItem Header=\"{lex:Loc logTabError}\" ContextMenu=\"{StaticResource ctx}\">\n                    <ScrollViewer>\n                        <Run Text=\"{Binding  Path=(cp:Logs.TbError)}\" />\n                    </ScrollViewer>\n                </TabItem>\n            </TabControl>\n        </materialDesign:Card>\n    </Grid>\n</UserControl>"
  },
  {
    "path": "WPF/ControlPanel/Pages/Logs.xaml.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.ComponentModel;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Runtime.CompilerServices;\nusing System.Text;\nusing System.Windows;\nusing System.Windows.Controls;\nusing ControlPanel.Pages.Menus;\nusing ControlPanel.ViewModels;\nusing MaterialDesignThemes.Wpf;\nusing VirtualSpace.AppLogs;\n\nnamespace ControlPanel.Pages;\n\npublic partial class Logs\n{\n    private static readonly StringBuilder SbDebug   = new();\n    private static readonly StringBuilder SbVerbose = new();\n    private static readonly StringBuilder SbEvent   = new();\n    private static readonly StringBuilder SbWarning = new();\n    private static readonly StringBuilder SbError   = new();\n    private static readonly StringBuilder SbInfo    = new();\n\n    private static Logs? _instance;\n\n    private Logs()\n    {\n        InitializeComponent();\n    }\n\n    private Logs( string headerKey, PackIconKind iconKind ) : this()\n    {\n        TcLogs.DataContext = this;\n\n        var mdc = (MenuContainerViewModel)MenuContainer.DataContext;\n        mdc.InjectContent = new LogsMenu();\n        mdc.HeaderKey = headerKey;\n        mdc.IconKind = iconKind;\n    }\n\n    public string this[ int index ]\n    {\n        set\n        {\n            switch ( index )\n            {\n                case 0:\n                    TbInfo = value;\n                    break;\n                case 1:\n                    TbDebug = value;\n                    break;\n                case 2:\n                    TbVerbose = value;\n                    break;\n                case 3:\n                    TbEvent = value;\n                    break;\n                case 4:\n                    TbWarning = value;\n                    break;\n                case 5:\n                    TbError = value;\n                    break;\n            }\n        }\n    }\n\n    public static string TbInfo\n    {\n        get => SbInfo.ToString();\n        set\n        {\n            if ( value is null )\n            {\n                SbInfo.Clear();\n            }\n            else\n            {\n                SbInfo.Append( value );\n            }\n\n            NotifyStaticPropertyChanged();\n        }\n    }\n\n    public static string TbDebug\n    {\n        get => SbDebug.ToString();\n        set\n        {\n            if ( value is null )\n            {\n                SbDebug.Clear();\n            }\n            else\n            {\n                SbDebug.Append( value );\n            }\n\n            NotifyStaticPropertyChanged();\n        }\n    }\n\n    public static string TbVerbose\n    {\n        get => SbVerbose.ToString();\n        set\n        {\n            if ( value is null )\n            {\n                SbVerbose.Clear();\n            }\n            else\n            {\n                SbVerbose.Append( value );\n            }\n\n            NotifyStaticPropertyChanged();\n        }\n    }\n\n    public static string TbEvent\n    {\n        get => SbEvent.ToString();\n        set\n        {\n            if ( value is null )\n            {\n                SbEvent.Clear();\n            }\n            else\n            {\n                SbEvent.Append( value );\n            }\n\n            NotifyStaticPropertyChanged();\n        }\n    }\n\n    public static string TbWarning\n    {\n        get => SbWarning.ToString();\n        set\n        {\n            if ( value is null )\n            {\n                SbWarning.Clear();\n            }\n            else\n            {\n                SbWarning.Append( value );\n            }\n\n            NotifyStaticPropertyChanged();\n        }\n    }\n\n    public static string TbError\n    {\n        get => SbError.ToString();\n        set\n        {\n            if ( value is null )\n            {\n                SbError.Clear();\n            }\n            else\n            {\n                SbError.Append( value );\n            }\n\n            NotifyStaticPropertyChanged();\n        }\n    }\n\n    public static Logs Create( string headerKey, PackIconKind iconKind )\n    {\n        return _instance ??= new Logs( headerKey, iconKind );\n    }\n\n    public static void Append( string message, string type )\n    {\n        switch ( type )\n        {\n            case \"INFO\":\n                TbInfo = message;\n                break;\n            case \"DEBUG\":\n                TbDebug = message;\n                break;\n            case \"VERBOSE\":\n                TbVerbose = message;\n                break;\n            case \"EVENT\":\n                TbEvent = message;\n                break;\n            case \"WARNING\":\n                TbWarning = message;\n                break;\n            case \"ERROR\":\n                TbError = message;\n                break;\n            default:\n                TbError = message;\n                break;\n        }\n    }\n\n    public static event EventHandler<PropertyChangedEventArgs>? StaticPropertyChanged;\n\n    private static void NotifyStaticPropertyChanged( [CallerMemberName] string? propertyName = null )\n    {\n        StaticPropertyChanged?.Invoke( null, new PropertyChangedEventArgs( propertyName ) );\n    }\n\n    private void Clear_Click( object sender, RoutedEventArgs e )\n    {\n        if ( sender is MenuItem mi )\n        {\n            if ( mi.CommandParameter is ContextMenu cm )\n            {\n                if ( cm.PlacementTarget is TabItem t )\n                {\n                    t.IsSelected = true;\n                    this[TcLogs.SelectedIndex] = null;\n                }\n            }\n        }\n    }\n\n    private void TabItem_OnContextMenuOpening( object sender, ContextMenuEventArgs e )\n    {\n        if ( e.Source is TabItem t )\n        {\n            t.IsSelected = true;\n        }\n    }\n\n    public static void ClearAll()\n    {\n        TbInfo = null;\n        TbDebug = null;\n        TbVerbose = null;\n        TbEvent = null;\n        TbWarning = null;\n        TbError = null;\n    }\n\n    public static void OpenLogsDir()\n    {\n        var logFolder = LogManager.LogsPath;\n        if ( !Directory.Exists( logFolder ) ) return;\n        var startInfo = new ProcessStartInfo\n        {\n            Arguments = logFolder,\n            FileName = \"explorer.exe\"\n        };\n\n        Process.Start( startInfo );\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Pages/Menus/Commons/MenuContainer.xaml",
    "content": "﻿<UserControl x:Class=\"ControlPanel.Pages.Menus.Commons.MenuContainer\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n             xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n             xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n             xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n             xmlns:lex=\"http://wpflocalizeextension.codeplex.com\"\n             xmlns:converters=\"clr-namespace:ControlPanel.Converters\"\n             mc:Ignorable=\"d\"\n             d:DesignHeight=\"300\" d:DesignWidth=\"300\">\n\n    <UserControl.Resources>\n        <ResourceDictionary>\n            <converters:ThemeConverter x:Key=\"ThemeConverter\" />\n        </ResourceDictionary>\n    </UserControl.Resources>\n\n    <materialDesign:Card Margin=\"10,10,10,0\"\n                         Background=\"{DynamicResource PrimaryHueMidBrush}\"\n                         Foreground=\"{DynamicResource PrimaryHueMidForegroundBrush}\">\n        <DockPanel>\n            <materialDesign:PopupBox DockPanel.Dock=\"Right\" Margin=\"10\"\n                                     PlacementMode=\"BottomAndAlignRightEdges\"\n                                     StaysOpen=\"True\">\n                <StackPanel>\n                    <StackPanel.Resources>\n                        <Style TargetType=\"Button\" BasedOn=\"{StaticResource MaterialDesignFlatButton}\">\n                            <Setter Property=\"Margin\" Value=\"5,0,5,5\" />\n                            <Setter Property=\"Padding\" Value=\"5\"></Setter>\n                            <Setter Property=\"HorizontalContentAlignment\" Value=\"Left\" />\n                        </Style>\n                    </StackPanel.Resources>\n                    <Border Margin=\"10\">\n                        <ListBox x:Name=\"ThemeSettings\" HorizontalAlignment=\"Center\" HorizontalContentAlignment=\"Center\"\n                                 SelectedIndex=\"{Binding Path=Theme, Converter={StaticResource ThemeConverter}, Mode=TwoWay}\"\n                                 Style=\"{StaticResource MaterialDesignToolToggleListBox}\">\n                            <ListBox.ToolTip>\n                                <TextBlock Text=\"{lex:Loc Menus.Commons.Theme.Change}\" TextAlignment=\"Center\" />\n                            </ListBox.ToolTip>\n                            <ListBoxItem Content=\"{materialDesign:PackIcon Kind=DesktopClassic}\" />\n                            <ListBoxItem Content=\"{materialDesign:PackIcon Kind=WhiteBalanceSunny}\" />\n                            <ListBoxItem Content=\"{materialDesign:PackIcon Kind=MoonWaxingCrescent}\" />\n                        </ListBox>\n                    </Border>\n\n                    <ContentControl Content=\"{Binding InjectContent}\" />\n\n                    <Separator />\n\n                    <Grid>\n                        <Grid.RowDefinitions>\n                            <RowDefinition></RowDefinition>\n                            <RowDefinition></RowDefinition>\n                            <RowDefinition></RowDefinition>\n                            <RowDefinition></RowDefinition>\n                            <RowDefinition></RowDefinition>\n                        </Grid.RowDefinitions>\n                        <Grid.ColumnDefinitions>\n                            <ColumnDefinition Width=\"32\"></ColumnDefinition>\n                            <ColumnDefinition></ColumnDefinition>\n                        </Grid.ColumnDefinitions>\n\n                        <Button Content=\"{lex:Loc Menus.Commons.Close}\" Click=\"CloseWindow_OnClick\" Grid.Column=\"1\" />\n                        <Separator Grid.Row=\"1\" Grid.Column=\"0\" Grid.ColumnSpan=\"2\" />\n                        <Image x:Name=\"SIID_SHIELD\" Grid.Row=\"2\" Grid.Column=\"0\"\n                               Width=\"16\" Height=\"16\" Margin=\"15,0,0,0\">\n                        </Image>\n                        <Button x:Name=\"menuItemRunAsAdmin\" Grid.Row=\"2\" Grid.Column=\"1\"\n                                Content=\"{lex:Loc Menus.Commons.RunAsAdmin}\" Click=\"MenuItemRunAsAdmin_OnClick\">\n                        </Button>\n\n                        <Button Grid.Row=\"3\" Grid.Column=\"1\"\n                                Content=\"{lex:Loc Menus.Commons.Restart}\" Click=\"RestartApp_OnClick\" />\n                        <Button Grid.Row=\"4\" Grid.Column=\"1\"\n                                Content=\"{lex:Loc Menus.Commons.Shutdown}\" Click=\"Shutdown_OnClick\" />\n                    </Grid>\n\n\n                </StackPanel>\n            </materialDesign:PopupBox>\n\n            <materialDesign:PackIcon Width=\"30\" Height=\"30\" Margin=\"10,0,0,0\"\n                                     Foreground=\"{DynamicResource MaterialDesignBody}\"\n                                     HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\"\n                                     Kind=\"{Binding IconKind}\" />\n            <TextBlock DockPanel.Dock=\"Left\" Margin=\"5,3,5,7\"\n                       HorizontalAlignment=\"Left\"\n                       VerticalAlignment=\"Center\"\n                       FontSize=\"30\" Foreground=\"{DynamicResource MaterialDesignBody}\"\n                       Text=\"{lex:Loc {Binding HeaderKey}}\" />\n        </DockPanel>\n    </materialDesign:Card>\n</UserControl>"
  },
  {
    "path": "WPF/ControlPanel/Pages/Menus/Commons/MenuContainer.xaml.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Drawing;\nusing System.Runtime.InteropServices;\nusing System.Windows;\nusing System.Windows.Controls;\nusing System.Windows.Interop;\nusing System.Windows.Media.Imaging;\nusing ControlPanel.ViewModels;\nusing VirtualSpace.Helpers;\n\nnamespace ControlPanel.Pages.Menus.Commons;\n\npublic partial class MenuContainer : UserControl\n{\n    public MenuContainer()\n    {\n        InitializeComponent();\n        DataContext = new MenuContainerViewModel();\n        ThemeSettings.DataContext = SettingsViewModel.GetInstance();\n        CheckAdmin();\n    }\n\n    private void CloseWindow_OnClick( object sender, RoutedEventArgs e )\n    {\n        MainWindow.TryClose();\n    }\n\n    private void RestartApp_OnClick( object sender, RoutedEventArgs e )\n    {\n        if ( Application.Current is App )\n        {\n            MainWindow.RestartApp();\n        }\n        else\n        {\n            User32.PostMessage( MainWindow.MainWindowHandle, WinMsg.WM_HOTKEY, UserMessage.RestartApp, 0 );\n        }\n    }\n\n    private void Shutdown_OnClick( object sender, RoutedEventArgs e )\n    {\n        if ( Application.Current is App )\n        {\n            MainWindow.TryQuit();\n        }\n        else\n        {\n            User32.PostMessage( MainWindow.MainWindowHandle, WinMsg.WM_CLOSE, 0, 0 );\n        }\n    }\n\n    private void CheckAdmin()\n    {\n        if ( SysInfo.IsAdministrator )\n        {\n            SIID_SHIELD.Visibility = Visibility.Collapsed;\n            menuItemRunAsAdmin.Visibility = Visibility.Collapsed;\n            return;\n        }\n\n        var iconResult = new SHSTOCKICONINFO();\n        iconResult.cbSize = (uint)Marshal.SizeOf( iconResult );\n\n        _ = User32.SHGetStockIconInfo( SHSTOCKICONID.SIID_SHIELD, SHGSI.SHGSI_ICON | SHGSI.SHGSI_SMALLICON, ref iconResult );\n        using var icon = Bitmap.FromHicon( iconResult.hIcon );\n        icon.MakeTransparent();\n\n        var iconSource      = Imaging.CreateBitmapSourceFromHBitmap( icon.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions() );\n        var writeableBitmap = new WriteableBitmap( iconSource );\n        SIID_SHIELD.Source = writeableBitmap;\n\n        SIID_SHIELD.Visibility = Visibility.Visible;\n        menuItemRunAsAdmin.Visibility = Visibility.Visible;\n    }\n\n    private void MenuItemRunAsAdmin_OnClick( object sender, RoutedEventArgs e )\n    {\n        User32.PostMessage( MainWindow.MainWindowHandle, WinMsg.WM_HOTKEY, UserMessage.RunAsAdministrator, 0 );\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Pages/Menus/LogsMenu.xaml",
    "content": "﻿<UserControl x:Class=\"ControlPanel.Pages.Menus.LogsMenu\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n             xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n             xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n             xmlns:lex=\"http://wpflocalizeextension.codeplex.com\"\n             mc:Ignorable=\"d\"\n             d:DesignHeight=\"300\" d:DesignWidth=\"300\">\n\n    <StackPanel>\n        <Separator />\n        <StackPanel Orientation=\"Horizontal\">\n            <TextBlock Margin=\"21,0,0,0\"\n                       Text=\"{lex:Loc Page.Logs.IsPrintLogs}\"\n                       VerticalAlignment=\"Center\" />\n            <ToggleButton\n                Style=\"{StaticResource MaterialDesignSwitchToggleButton}\"\n                Width=\"50\" Margin=\"5,5\"\n                IsChecked=\"{Binding IsPrintLogs, Mode=TwoWay}\" />\n        </StackPanel>\n\n        <Grid>\n            <Grid.RowDefinitions>\n                <RowDefinition></RowDefinition>\n                <RowDefinition></RowDefinition>\n            </Grid.RowDefinitions>\n            <Grid.ColumnDefinitions>\n                <ColumnDefinition Width=\"32\"></ColumnDefinition>\n                <ColumnDefinition></ColumnDefinition>\n            </Grid.ColumnDefinitions>\n            <Button Content=\"{lex:Loc Menus.Logs.ClearAll}\" Grid.Column=\"1\" Click=\"clearAll_OnClick\" />\n            <Button Grid.Row=\"1\" Grid.Column=\"1\" Content=\"{lex:Loc Menus.Logs.OpenLogsDir}\" Click=\"openLogsDir_OnClick\" />\n        </Grid>\n    </StackPanel>\n\n</UserControl>"
  },
  {
    "path": "WPF/ControlPanel/Pages/Menus/LogsMenu.xaml.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.Windows;\nusing System.Windows.Controls;\nusing ControlPanel.ViewModels;\n\nnamespace ControlPanel.Pages.Menus;\n\npublic partial class LogsMenu : UserControl\n{\n    public LogsMenu()\n    {\n        InitializeComponent();\n        DataContext = new LogsViewModel();\n    }\n\n    private void clearAll_OnClick( object sender, RoutedEventArgs e )\n    {\n        Logs.ClearAll();\n    }\n\n    private void openLogsDir_OnClick( object sender, RoutedEventArgs e )\n    {\n        Logs.OpenLogsDir();\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Pages/Plugins.xaml",
    "content": "﻿<UserControl x:Class=\"ControlPanel.Pages.Plugins\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n             xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n             xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n             xmlns:commons=\"clr-namespace:ControlPanel.Pages.Menus.Commons\"\n             xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n             xmlns:lex=\"http://wpflocalizeextension.codeplex.com\"\n             mc:Ignorable=\"d\">\n\n    <UserControl.Resources>\n        <ResourceDictionary>\n            <Style TargetType=\"ScrollViewer\">\n                <Setter Property=\"Margin\" Value=\"5\" />\n            </Style>\n        </ResourceDictionary>\n    </UserControl.Resources>\n\n    <Grid>\n        <Grid.RowDefinitions>\n            <RowDefinition Height=\"Auto\" />\n            <RowDefinition Height=\"*\" />\n        </Grid.RowDefinitions>\n        <Grid Grid.Row=\"0\">\n            <commons:MenuContainer x:Name=\"MenuContainer\" />\n        </Grid>\n        <Grid Grid.Row=\"1\">\n            <materialDesign:Card materialDesign:ElevationAssist.Elevation=\"Dp2\" Margin=\"10,10,10,12\">\n                <ListView x:Name=\"PluginsList\" ItemsSource=\"{Binding Plugins}\">\n                    <ListView.View>\n                        <GridView>\n                            <GridViewColumn>\n                                <GridViewColumn.CellTemplate>\n                                    <DataTemplate>\n                                        <CheckBox IsChecked=\"{Binding AutoStart}\"\n                                                  Checked=\"ToggleButton_OnChecked\"\n                                                  Unchecked=\"ToggleButton_OnUnchecked\"\n                                                  CommandParameter=\"{Binding Name}\" />\n                                    </DataTemplate>\n                                </GridViewColumn.CellTemplate>\n                            </GridViewColumn>\n                            <GridViewColumn Width=\"100\"\n                                            DisplayMemberBinding=\"{Binding Name}\"\n                                            Header=\"{lex:Loc Page.Plugins.Name}\" />\n                            <GridViewColumn\n                                Header=\"{lex:Loc Page.Plugins.Version}\">\n                                <GridViewColumn.CellTemplate>\n                                    <DataTemplate>\n                                        <TextBlock TextAlignment=\"Center\" Width=\"120\" Text=\"{Binding Version}\" />\n                                    </DataTemplate>\n                                </GridViewColumn.CellTemplate>\n                            </GridViewColumn>\n                            <GridViewColumn\n                                DisplayMemberBinding=\"{Binding Author}\"\n                                Header=\"{lex:Loc Page.Plugins.Author}\" />\n                            <GridViewColumn Width=\"200\"\n                                            DisplayMemberBinding=\"{Binding Email}\"\n                                            Header=\"{lex:Loc Page.Plugins.Email}\" />\n                            <GridViewColumn\n                                Header=\"{lex:Loc Page.Plugins.Operations}\">\n                                <GridViewColumn.CellTemplate>\n                                    <DataTemplate>\n                                        <materialDesign:PopupBox\n                                            Margin=\"30,0,0,0\"\n                                            StaysOpen=\"False\"\n                                            PlacementMode=\"BottomAndAlignRightEdges\">\n                                            <ListBox SelectionChanged=\"Selector_OnSelectionChanged\" MinWidth=\"100\">\n                                                <ListBoxItem\n                                                    Content=\"{lex:Loc Page.Plugins.Settings}\" Tag=\"{Binding Name}\" />\n                                                <ListBoxItem\n                                                    Content=\"{lex:Loc Page.Plugins.Restart}\" Tag=\"{Binding Name}\" />\n                                                <ListBoxItem\n                                                    Content=\"{lex:Loc Page.Plugins.Close}\" Tag=\"{Binding Name}\" />\n                                            </ListBox>\n                                        </materialDesign:PopupBox>\n                                    </DataTemplate>\n                                </GridViewColumn.CellTemplate>\n                            </GridViewColumn>\n                        </GridView>\n                    </ListView.View>\n                </ListView>\n            </materialDesign:Card>\n        </Grid>\n    </Grid>\n</UserControl>"
  },
  {
    "path": "WPF/ControlPanel/Pages/Plugins.xaml.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System.Linq;\nusing System.Windows;\nusing System.Windows.Controls;\nusing ControlPanel.ViewModels;\nusing MaterialDesignThemes.Wpf;\nusing VirtualSpace.Plugin;\n\nnamespace ControlPanel.Pages;\n\npublic partial class Plugins\n{\n    private static Plugins? _instance;\n\n    private Plugins()\n    {\n        InitializeComponent();\n    }\n\n    private Plugins( string headerKey, PackIconKind iconKind ) : this()\n    {\n        PluginsList.DataContext = new PluginsViewModel();\n        var mdc = (MenuContainerViewModel)MenuContainer.DataContext;\n        mdc.HeaderKey = headerKey;\n        mdc.IconKind = iconKind;\n    }\n\n    public static Plugins Create( string headerKey, PackIconKind iconKind )\n    {\n        return _instance ??= new Plugins( headerKey, iconKind );\n    }\n\n    private void ToggleButton_OnChecked( object sender, RoutedEventArgs e )\n    {\n        var chb        = sender as CheckBox;\n        var name       = chb.CommandParameter as string;\n        var pvm        = PluginsList.DataContext as PluginsViewModel;\n        var pluginInfo = pvm.Plugins.First( p => p.Name == name );\n\n        pluginInfo.AutoStart = true;\n        PluginHost.StartPlugin( pluginInfo );\n        PluginManager.SavePluginInfo( pluginInfo );\n    }\n\n    private void ToggleButton_OnUnchecked( object sender, RoutedEventArgs e )\n    {\n        var chb        = sender as CheckBox;\n        var name       = chb.CommandParameter as string;\n        var pvm        = PluginsList.DataContext as PluginsViewModel;\n        var pluginInfo = pvm.Plugins.First( p => p.Name == name );\n\n        pluginInfo.AutoStart = false;\n        PluginHost.ClosePlugin( pluginInfo );\n        PluginManager.SavePluginInfo( pluginInfo );\n    }\n\n    private void Selector_OnSelectionChanged( object sender, SelectionChangedEventArgs e )\n    {\n        var lb = sender as ListBox;\n        if ( lb.SelectedIndex == -1 ) return;\n        var lbi        = lb.SelectedItem as ListBoxItem;\n        var name       = lbi.Tag as string;\n        var pvm        = PluginsList.DataContext as PluginsViewModel;\n        var pluginInfo = pvm.Plugins.First( p => p.Name == name );\n\n        switch ( lb.SelectedIndex )\n        {\n            case 0:\n                PluginHost.PluginSettings( pluginInfo );\n                break;\n            case 1:\n                PluginHost.RestartPlugin( pluginInfo );\n                break;\n            case 2:\n                PluginHost.ClosePlugin( pluginInfo );\n                break;\n        }\n\n        lb.SelectedIndex = -1;\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Pages/Rules.ue.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Collections;\nusing System.ComponentModel;\nusing System.Windows;\nusing System.Windows.Controls;\nusing System.Windows.Data;\nusing System.Windows.Input;\nusing VirtualSpace.Config.Events.Entity;\n\nnamespace ControlPanel.Pages;\n\npublic partial class Rules\n{\n    private ListSortDirection    _lastDirection = ListSortDirection.Ascending;\n    private GridViewColumnHeader _lastHeaderClicked;\n    private bool                 _needRefresh;\n\n    private void RuleList_OnLoaded( object sender, RoutedEventArgs e )\n    {\n        if ( !_needRefresh ) return;\n        SortSelectedColumn( DefaultSortColumnHeader, ListSortDirection.Descending, RuleList.ItemsSource );\n        var view = (CollectionView)CollectionViewSource.GetDefaultView( RuleList.ItemsSource );\n        view.Filter = NameFilter;\n\n        view.GroupDescriptions.Clear();\n        var groupDescription = new PropertyGroupDescription( \"Tag\" );\n        view.GroupDescriptions.Add( groupDescription );\n        _needRefresh = false;\n    }\n\n    private bool NameFilter( object item )\n    {\n        if ( string.IsNullOrEmpty( tbNameFilter.Text ) )\n            return true;\n\n        var keyword = tbNameFilter.Text.Trim();\n        if ( keyword is @\"\\\" or @\"\\\\\" or @\"\\\\G\" )\n            return true;\n\n        if ( keyword.StartsWith( @\"\\\\G\" ) && keyword.Length > 3 )\n        {\n            keyword = keyword[3..];\n            return ( item as RuleTemplate ).Tag?.IndexOf( keyword, StringComparison.OrdinalIgnoreCase ) >= 0;\n        }\n\n        return ( item as RuleTemplate ).Name.IndexOf( tbNameFilter.Text, StringComparison.OrdinalIgnoreCase ) >= 0;\n    }\n\n    private void TbNameFilter_OnTextChanged( object sender, TextChangedEventArgs e )\n    {\n        CollectionViewSource.GetDefaultView( RuleList.ItemsSource ).Refresh();\n    }\n\n    private void RuleList_OnPreviewKeyDown( object sender, KeyEventArgs e )\n    {\n        switch ( e.Key )\n        {\n            case Key.Delete:\n                BtnDeleteRule_OnClick( sender, e );\n                break;\n            case Key.E:\n                BtnEditRule_OnClick( sender, e );\n                break;\n        }\n    }\n\n    private void SortSelectedColumn( GridViewColumnHeader targetHeader, ListSortDirection direction, IEnumerable itemsSource )\n    {\n        var columnBinding = targetHeader.Column.DisplayMemberBinding as Binding;\n        var sortBy        = columnBinding?.Path.Path ?? targetHeader.Column.Header as string;\n\n        void Sort( string sortBy, ListSortDirection direction )\n        {\n            var dataView = (CollectionView)CollectionViewSource.GetDefaultView( itemsSource );\n            dataView.SortDescriptions.Clear();\n            var sd = new SortDescription( sortBy, direction );\n            dataView.SortDescriptions.Add( sd );\n            dataView.Refresh();\n        }\n\n        Sort( sortBy, direction );\n\n        if ( direction == ListSortDirection.Ascending )\n        {\n            targetHeader.Column.HeaderTemplate = Resources[\"HeaderTemplateArrowUp\"] as DataTemplate;\n        }\n        else\n        {\n            targetHeader.Column.HeaderTemplate = Resources[\"HeaderTemplateArrowDown\"] as DataTemplate;\n        }\n\n        if ( _lastHeaderClicked != null && _lastHeaderClicked != targetHeader )\n        {\n            _lastHeaderClicked.Column.HeaderTemplate = null;\n        }\n\n        _lastHeaderClicked = targetHeader;\n        _lastDirection = direction;\n    }\n\n    private void RuleList_OnColumnHeaderClick( object sender, RoutedEventArgs e )\n    {\n        var headerClicked = e.OriginalSource as GridViewColumnHeader;\n        if ( headerClicked == null ||\n             headerClicked.Role == GridViewColumnHeaderRole.Padding ) return;\n\n        ListSortDirection direction;\n        if ( headerClicked != _lastHeaderClicked )\n        {\n            direction = ListSortDirection.Ascending;\n        }\n        else\n        {\n            direction = _lastDirection == ListSortDirection.Ascending ? ListSortDirection.Descending : ListSortDirection.Ascending;\n        }\n\n        SortSelectedColumn( headerClicked, direction, RuleList.ItemsSource );\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Pages/Rules.xaml",
    "content": "﻿<UserControl x:Class=\"ControlPanel.Pages.Rules\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n             xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n             xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n             xmlns:commons=\"clr-namespace:ControlPanel.Pages.Menus.Commons\"\n             xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n             xmlns:lex=\"http://wpflocalizeextension.codeplex.com\"\n             xmlns:converters=\"clr-namespace:ControlPanel.Converters\"\n             xmlns:userControls=\"clr-namespace:ControlPanel.Pages.UserControls\"\n             mc:Ignorable=\"d\">\n\n    <UserControl.Resources>\n        <ResourceDictionary>\n            <Style TargetType=\"ScrollViewer\">\n                <Setter Property=\"Margin\" Value=\"5\" />\n            </Style>\n            <Style TargetType=\"GroupBox\" BasedOn=\"{StaticResource MaterialDesignGroupBox}\">\n                <Setter Property=\"HeaderTemplate\">\n                    <Setter.Value>\n                        <DataTemplate>\n                            <TextBlock Foreground=\"{DynamicResource MaterialDesignBody}\" Text=\"{Binding}\" FontWeight=\"Bold\" FontSize=\"14\" />\n                        </DataTemplate>\n                    </Setter.Value>\n                </Setter>\n            </Style>\n            <Style TargetType=\"Button\" BasedOn=\"{StaticResource MaterialDesignPaperSecondaryLightButton}\">\n                <Setter Property=\"Margin\" Value=\"10,5\" />\n                <Setter Property=\"Height\" Value=\"50\" />\n            </Style>\n            <converters:DrawerStateMutexConverter x:Key=\"DrawerStateMutexConverter\" />\n            <converters:WidthHeightConverter x:Key=\"WidthHeightConverter\" />\n            <converters:RuleHeaderByStateConverter x:Key=\"RuleHeaderByStateConverter\" />\n            <DataTemplate x:Key=\"HeaderTemplateArrowUp\">\n                <DockPanel>\n                    <materialDesign:PackIcon Kind=\"ArrowUp\"></materialDesign:PackIcon>\n                    <TextBlock HorizontalAlignment=\"Center\" Text=\"{Binding}\" />\n                </DockPanel>\n            </DataTemplate>\n            <DataTemplate x:Key=\"HeaderTemplateArrowDown\">\n                <DockPanel>\n                    <materialDesign:PackIcon Kind=\"ArrowDown\"></materialDesign:PackIcon>\n                    <TextBlock HorizontalAlignment=\"Center\" Text=\"{Binding}\" />\n                </DockPanel>\n            </DataTemplate>\n        </ResourceDictionary>\n    </UserControl.Resources>\n\n    <Grid x:Name=\"RulesFrame\">\n        <Grid.RowDefinitions>\n            <RowDefinition Height=\"Auto\" />\n            <RowDefinition Height=\"*\" />\n            <RowDefinition Height=\"Auto\" />\n        </Grid.RowDefinitions>\n\n        <commons:MenuContainer x:Name=\"MenuContainer\" Grid.Row=\"0\" />\n\n        <materialDesign:Card materialDesign:ElevationAssist.Elevation=\"Dp2\" Grid.Row=\"1\" Margin=\"10,10,10,0\"\n                             Visibility=\"{Binding Path=IsBottomDrawerOpen, ElementName=DrawerHost, Converter={StaticResource DrawerStateMutexConverter}}\">\n            <ListView x:Name=\"RuleList\" SelectionMode=\"Single\"\n                      SelectionChanged=\"RuleList_OnSelectionChanged\"\n                      PreviewKeyDown=\"RuleList_OnPreviewKeyDown\"\n                      ScrollViewer.HorizontalScrollBarVisibility=\"Disabled\"\n                      GridViewColumnHeader.Click=\"RuleList_OnColumnHeaderClick\" Loaded=\"RuleList_OnLoaded\">\n                <ListView.Resources>\n                    <Style x:Key=\"{x:Static GridView.GridViewScrollViewerStyleKey}\"\n                           BasedOn=\"{StaticResource {x:Static GridView.GridViewScrollViewerStyleKey}}\"\n                           TargetType=\"ScrollViewer\">\n                        <Setter Property=\"CanContentScroll\" Value=\"False\" />\n                    </Style>\n                    <Style TargetType=\"GridViewColumnHeader\" BasedOn=\"{StaticResource {x:Type GridViewColumnHeader}}\">\n                        <Setter Property=\"Padding\" Value=\"10 5\"></Setter>\n                    </Style>\n                </ListView.Resources>\n                <ListView.GroupStyle>\n                    <GroupStyle>\n                        <GroupStyle.HeaderTemplate>\n                            <DataTemplate>\n                                <TextBlock FontWeight=\"Bold\" FontSize=\"14\" Margin=\"10,0\" Text=\"{Binding Name}\" />\n                            </DataTemplate>\n                        </GroupStyle.HeaderTemplate>\n                    </GroupStyle>\n                </ListView.GroupStyle>\n                <ListView.View>\n                    <GridView>\n                        <GridViewColumn>\n                            <GridViewColumn.CellTemplate>\n                                <DataTemplate>\n                                    <CheckBox IsChecked=\"{Binding Enabled, UpdateSourceTrigger=PropertyChanged}\" />\n                                </DataTemplate>\n                            </GridViewColumn.CellTemplate>\n                        </GridViewColumn>\n                        <GridViewColumn Width=\"{Binding Path=ActualWidth,ElementName=RuleList,Converter={StaticResource WidthHeightConverter},ConverterParameter=500}\"\n                                        DisplayMemberBinding=\"{Binding Name}\"\n                                        Header=\"{lex:Loc Generic.Name}\">\n                        </GridViewColumn>\n                        <GridViewColumn Width=\"100\" DisplayMemberBinding=\"{Binding Weight}\">\n                            <GridViewColumnHeader x:Name=\"DefaultSortColumnHeader\" Content=\"{lex:Loc Page.Rules.Weight}\"></GridViewColumnHeader>\n                        </GridViewColumn>\n                        <GridViewColumn Width=\"150\" DisplayMemberBinding=\"{Binding Created,StringFormat={}{0:yyyy-MM-dd HH:mm}}\"\n                                        Header=\"{lex:Loc Page.Rules.Created}\">\n                        </GridViewColumn>\n                        <GridViewColumn Width=\"150\" DisplayMemberBinding=\"{Binding Updated,StringFormat={}{0:yyyy-MM-dd HH:mm}}\"\n                                        Header=\"{lex:Loc Page.Rules.Updated}\" />\n                    </GridView>\n                </ListView.View>\n            </ListView>\n        </materialDesign:Card>\n\n        <materialDesign:DrawerHost Grid.Row=\"2\" x:Name=\"DrawerHost\"\n                                   OverlayBackground=\"Transparent\" Width=\"{Binding ActualWidth, ElementName=MenuContainer}\"\n                                   MinWidth=\"700\" Margin=\"10\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" BottomDrawerCornerRadius=\"10\">\n\n            <materialDesign:DrawerHost.BottomDrawerContent>\n                <GroupBox MinHeight=\"680\" VerticalAlignment=\"Top\" Margin=\"10,0\"\n                          Header=\"{lex:Loc {Binding Path=Id,Converter={StaticResource RuleHeaderByStateConverter}}}\"\n                          Height=\"{Binding Path=ActualHeight,ElementName=RulesFrame,Converter={StaticResource WidthHeightConverter},ConverterParameter=80}\">\n                    <userControls:RuleForm x:Name=\"UserControlRuleEditor\"></userControls:RuleForm>\n                </GroupBox>\n            </materialDesign:DrawerHost.BottomDrawerContent>\n\n            <Grid>\n                <Grid.ColumnDefinitions>\n                    <ColumnDefinition Width=\"*\" />\n                    <ColumnDefinition Width=\"Auto\" />\n                </Grid.ColumnDefinitions>\n                <TextBox x:Name=\"tbNameFilter\" MinWidth=\"200\" Width=\"300\" Margin=\"10,0\"\n                         HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" Padding=\"0\"\n                         materialDesign:HintAssist.FloatingScale=\"0.80\"\n                         materialDesign:HintAssist.Hint=\"{lex:Loc Generic.Filter}\"\n                         materialDesign:TextFieldAssist.TextBoxViewMargin=\"1 0 1 0\"\n                         Style=\"{StaticResource MaterialDesignFloatingHintTextBox}\"\n                         TextChanged=\"TbNameFilter_OnTextChanged\">\n                </TextBox>\n                <StackPanel Grid.Column=\"1\" Orientation=\"Horizontal\">\n                    <Button Content=\"{lex:Loc Page.Rules.Add}\" Click=\"BtnNewRule_OnClick\" />\n                    <Button x:Name=\"btnEditRule\" Content=\"{lex:Loc Page.Rules.Edit}\" IsEnabled=\"False\" Click=\"BtnEditRule_OnClick\" />\n                    <Button x:Name=\"btnCloneRule\" Content=\"{lex:Loc Page.Rules.Clone}\" IsEnabled=\"False\" Click=\"BtnCloneRule_OnClick\" />\n                    <Button x:Name=\"btnDeleteRule\" Content=\"{lex:Loc Page.Rules.Delete}\" IsEnabled=\"False\" Click=\"BtnDeleteRule_OnClick\" />\n                </StackPanel>\n            </Grid>\n\n        </materialDesign:DrawerHost>\n\n    </Grid>\n</UserControl>"
  },
  {
    "path": "WPF/ControlPanel/Pages/Rules.xaml.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Text.Json;\nusing System.Windows;\nusing System.Windows.Controls;\nusing ControlPanel.ViewModels;\nusing MaterialDesignThemes.Wpf;\nusing VirtualSpace.Config.Events.Entity;\nusing VirtualSpace.Config.Events.Expression;\n\nnamespace ControlPanel.Pages;\n\npublic partial class Rules\n{\n    private static Rules? _instance;\n\n    private Rules()\n    {\n        _instance = this;\n        InitializeComponent();\n    }\n\n    private Rules( string headerKey, PackIconKind iconKind ) : this()\n    {\n        var mdc = (MenuContainerViewModel)MenuContainer.DataContext;\n        mdc.HeaderKey = headerKey;\n        mdc.IconKind = iconKind;\n\n        ReloadRules();\n        HandleClick();\n\n        UserControlRuleEditor.RuleListItemsSource = RuleList.ItemsSource as FullObservableCollection<RuleTemplate>;\n    }\n\n    public static void ReloadRules()\n    {\n        _instance.RuleList.ItemsSource = RulesViewModel.Instance.Rules;\n        _instance._needRefresh = true;\n    }\n\n    private void HandleClick()\n    {\n        AddHandler( Button.ClickEvent, new RoutedEventHandler( ClickEventFromSubControl ) );\n    }\n\n    private void ClickEventFromSubControl( object sender, RoutedEventArgs e )\n    {\n        if ( e.OriginalSource is Button btn )\n        {\n            switch ( btn.Name )\n            {\n                case \"btnSave\":\n                case \"btnCloseDefBox\":\n\n                    DrawerHost.IsBottomDrawerOpen = false;\n                    e.Handled = true;\n                    break;\n            }\n        }\n    }\n\n    public static Rules Create( string headerKey, PackIconKind iconKind )\n    {\n        return _instance ??= new Rules( headerKey, iconKind );\n    }\n\n    private void RuleList_OnSelectionChanged( object sender, SelectionChangedEventArgs e )\n    {\n        UserControlRuleEditor.RuleDefBox.DataContext = RuleList.SelectedItem; // 笑看风云变\n\n        btnEditRule.IsEnabled = RuleList.SelectedItems.Count > 0;\n        btnCloneRule.IsEnabled = RuleList.SelectedItems.Count > 0;\n        btnDeleteRule.IsEnabled = RuleList.SelectedItems.Count > 0;\n    }\n\n    private void BtnEditRule_OnClick( object sender, RoutedEventArgs e )\n    {\n        var r = RuleList.SelectedItem as RuleTemplate;\n        if ( r == null ) return;\n\n        UserControlRuleEditor.RuleDate.Visibility = Visibility.Visible;\n\n        DrawerHost.IsBottomDrawerOpen = true;\n    }\n\n    private void BtnNewRule_OnClick( object sender, RoutedEventArgs e )\n    {\n        RuleList.SelectedIndex = -1;\n\n        UserControlRuleEditor.RuleDefBox.DataContext = new RuleTemplate // 平地起风云\n        {\n            Id = Guid.Empty,\n            Enabled = true,\n            Action = new Behavior()\n        };\n        UserControlRuleEditor.RuleDate.Visibility = Visibility.Hidden;\n\n        DrawerHost.IsBottomDrawerOpen = true;\n    }\n\n    private void BtnCloneRule_OnClick( object sender, RoutedEventArgs e )\n    {\n        var r = RuleList.SelectedItem as RuleTemplate;\n        if ( r == null ) return;\n\n        var foc  = RuleList.ItemsSource as FullObservableCollection<RuleTemplate>;\n        var time = DateTime.Now;\n\n        var et = RefreshRuleIds( Conditions.ParseExpressionTemplate( r.Expression ) );\n\n        var clone = new RuleTemplate\n        {\n            Name = r.Name,\n            Expression = JsonDocument.Parse( JsonSerializer.Serialize( et, RulesViewModel.WriteOptions ) ),\n            Enabled = r.Enabled,\n            Tag = r.Tag,\n            Action = r.Action!.Clone(),\n            Created = time,\n            Updated = time\n        };\n\n        foc.Add( clone );\n    }\n\n    private void BtnDeleteRule_OnClick( object sender, RoutedEventArgs e )\n    {\n        var r = RuleList.SelectedItem as RuleTemplate;\n        if ( r == null ) return;\n\n        var foc = RuleList.ItemsSource as FullObservableCollection<RuleTemplate>;\n        foc.Remove( r );\n    }\n\n    private static ExpressionTemplate RefreshRuleIds( ExpressionTemplate expressionTemplate )\n    {\n        expressionTemplate.id = Guid.NewGuid();\n        if ( expressionTemplate.rules == null ) return expressionTemplate;\n\n        foreach ( var rule in expressionTemplate.rules )\n        {\n            rule.id = Guid.NewGuid();\n            if ( rule.rules != null ) RefreshRuleIds( rule );\n        }\n\n        return expressionTemplate;\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Pages/Settings.xaml",
    "content": "﻿<UserControl x:Class=\"ControlPanel.Pages.Settings\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n             xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n             xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n             xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n             xmlns:lex=\"http://wpflocalizeextension.codeplex.com\"\n             xmlns:cvts=\"clr-namespace:ControlPanel.Converters\"\n             xmlns:vsb=\"clr-namespace:VirtualSpace;assembly=Bridge\"\n             mc:Ignorable=\"d\">\n\n    <UserControl.Resources>\n        <ResourceDictionary>\n            <cvts:CheckBoxConverter x:Key=\"CheckBoxConverter\" />\n            <Style TargetType=\"GroupBox\" BasedOn=\"{StaticResource MaterialDesignGroupBox}\">\n                <Setter Property=\"HeaderTemplate\">\n                    <Setter.Value>\n                        <DataTemplate>\n                            <TextBlock Foreground=\"{DynamicResource MaterialDesignBody}\" Text=\"{Binding}\" FontWeight=\"Bold\" FontSize=\"20\" />\n                        </DataTemplate>\n                    </Setter.Value>\n                </Setter>\n            </Style>\n            <Style TargetType=\"Button\" BasedOn=\"{StaticResource MaterialDesignPaperSecondaryLightButton}\">\n                <Setter Property=\"Margin\" Value=\"10,5\" />\n                <Setter Property=\"Height\" Value=\"50\" />\n            </Style>\n        </ResourceDictionary>\n    </UserControl.Resources>\n\n    <materialDesign:DialogHost Identifier=\"ProfileDialog\">\n        <Grid>\n            <Grid.RowDefinitions>\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n            </Grid.RowDefinitions>\n\n            <StackPanel Orientation=\"Horizontal\">\n                <GroupBox\n                    VerticalAlignment=\"Top\"\n                    Margin=\"10\"\n                    Width=\"250\" Height=\"{Binding Path=Children[1].ActualHeight, RelativeSource={RelativeSource AncestorType=StackPanel}}\"\n                    Header=\"{lex:Loc Page.Settings.Language}\">\n                    <ComboBox\n                        VerticalAlignment=\"Top\" Height=\"50\" Margin=\"5\"\n                        ItemsSource=\"{x:Static vsb:Agent.ValidLangs}\"\n                        Style=\"{StaticResource MaterialDesignFilledComboBox}\"\n                        SelectedValue=\"{Binding Language}\"\n                        SelectedValuePath=\"Key\" DisplayMemberPath=\"Value\" />\n                </GroupBox>\n                <GroupBox\n                    VerticalAlignment=\"Top\"\n                    Margin=\"10\"\n                    Width=\"250\"\n                    Header=\"{lex:Loc Page.Settings.Theme}\">\n                    <StackPanel Orientation=\"Vertical\">\n                        <StackPanel.Resources>\n                            <Style TargetType=\"RadioButton\" BasedOn=\"{StaticResource MaterialDesignLightRadioButton}\">\n                                <Setter Property=\"Margin\" Value=\"10,5,0,5\" />\n                            </Style>\n                        </StackPanel.Resources>\n                        <RadioButton\n                            Content=\"{lex:Loc Page.Settings.Theme.Sys}\"\n                            IsChecked=\"{Binding Theme,Converter={StaticResource CheckBoxConverter},ConverterParameter=0}\"\n                            Tag=\"sys\" />\n                        <RadioButton\n                            Content=\"{lex:Loc Page.Settings.Theme.Light}\"\n                            IsChecked=\"{Binding Theme,Converter={StaticResource CheckBoxConverter},ConverterParameter=1}\"\n                            Tag=\"light\" />\n                        <RadioButton\n                            Content=\"{lex:Loc Page.Settings.Theme.Dark}\"\n                            IsChecked=\"{Binding Theme,Converter={StaticResource CheckBoxConverter},ConverterParameter=2}\"\n                            Tag=\"dark\" />\n                    </StackPanel>\n                </GroupBox>\n            </StackPanel>\n\n            <GroupBox Grid.Row=\"1\"\n                      Margin=\"10\"\n                      Header=\"{lex:Loc Page.Settings.Storage}\">\n                <StackPanel>\n                    <DockPanel>\n                        <Button DockPanel.Dock=\"Right\" Content=\"{lex:Loc Page.Settings.Storage.ChangeConfigPath}\" Click=\"ChangeConfigPath_OnClick\"></Button>\n                        <TextBox x:Name=\"tbConfigPath\" IsReadOnly=\"True\" Focusable=\"False\"\n                                 MinWidth=\"500\" FontSize=\"20\" Margin=\"0\"\n                                 materialDesign:HintAssist.FloatingScale=\"0.80\"\n                                 materialDesign:HintAssist.Hint=\"{lex:Loc Page.Settings.Storage.ConfigRootPath}\"\n                                 materialDesign:TextFieldAssist.TextBoxViewMargin=\"1 0 1 0\"\n                                 Style=\"{StaticResource MaterialDesignFloatingHintTextBox}\"\n                                 Text=\"{Binding ConfigRootPath}\">\n\n                        </TextBox>\n                    </DockPanel>\n\n                    <materialDesign:Chip Height=\"70\" Margin=\"0,5,0,0\" Content=\"{lex:Loc Note.Settings.Storage}\" />\n\n                </StackPanel>\n            </GroupBox>\n            <GroupBox Grid.Row=\"2\"\n                      VerticalAlignment=\"Top\"\n                      Margin=\"10\"\n                      Header=\"{lex:Loc Page.Settings.ProfileManager}\">\n                <StackPanel>\n                    <StackPanel Orientation=\"Horizontal\">\n                        <ComboBox x:Name=\"cbbProfiles\"\n                                  MinWidth=\"500\"\n                                  Style=\"{StaticResource MaterialDesignFilledComboBox}\"\n                                  ItemsSource=\"{Binding ProfileList}\"\n                                  SelectedValuePath=\"Value\" DisplayMemberPath=\"Value\"\n                                  SelectedValue=\"{Binding CurrentProfile}\">\n                        </ComboBox>\n\n                        <materialDesign:PopupBox DockPanel.Dock=\"Right\" Margin=\"10\" MinWidth=\"100\"\n                                                 PlacementMode=\"BottomAndAlignRightEdges\"\n                                                 StaysOpen=\"False\">\n                            <StackPanel>\n                                <Button Content=\"{lex:Loc Page.Settings.Menus.Duplicate}\" Click=\"ProfileClone_OnClick\" />\n                                <Button Content=\"{lex:Loc Page.Settings.Menus.Rename}\" Click=\"ProfileRename_OnClick\" />\n\n                                <Separator />\n                                <Button Content=\"{lex:Loc Page.Settings.Menus.Delete}\" Click=\"ProfileRemove_OnClick\" />\n                            </StackPanel>\n                        </materialDesign:PopupBox>\n\n                    </StackPanel>\n\n                    <materialDesign:Chip Height=\"70\" Margin=\"0,5,0,0\" Content=\"{lex:Loc Note.Settings.Profiles}\" />\n                </StackPanel>\n            </GroupBox>\n        </Grid>\n    </materialDesign:DialogHost>\n</UserControl>"
  },
  {
    "path": "WPF/ControlPanel/Pages/Settings.xaml.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System.IO;\nusing System.Linq;\nusing System.Windows;\nusing System.Windows.Forms;\nusing ControlPanel.Pages.Dialogs;\nusing ControlPanel.ViewModels;\nusing MaterialDesignThemes.Wpf;\nusing VirtualSpace;\nusing VirtualSpace.Config;\nusing VirtualSpace.Config.Events.Expression;\n\nnamespace ControlPanel.Pages;\n\npublic partial class Settings\n{\n    private static Settings? _instance;\n\n    private Settings()\n    {\n        InitializeComponent();\n\n        DataContext = SettingsViewModel.GetInstance();\n    }\n\n    public static Settings Create()\n    {\n        return _instance ??= new Settings();\n    }\n\n    private void ChangeConfigPath_OnClick( object sender, RoutedEventArgs e )\n    {\n        using var fbd = new FolderBrowserDialog();\n\n        if ( fbd.ShowDialog() == DialogResult.OK && !string.IsNullOrWhiteSpace( fbd.SelectedPath ) )\n        {\n            var vm = DataContext as SettingsViewModel;\n            vm.ConfigRootPath = fbd.SelectedPath;\n            Manager.SetConfigRoot( fbd.SelectedPath );\n        }\n    }\n\n    private async void ProfileClone_OnClick( object sender, RoutedEventArgs e )\n    {\n        var newProfileName = cbbProfiles.Text + \" (copy)\";\n\n        var isValid = !string.IsNullOrEmpty( newProfileName ) &&\n                      newProfileName.IndexOfAny( Path.GetInvalidFileNameChars() ) < 0 &&\n                      !File.Exists( Path.Combine( Manager.ProfileFolder, newProfileName ) );\n\n        if ( Manager.Configs.Profiles.ContainsKey( newProfileName ) || !isValid )\n        {\n            var view = new YesNoWithNote( Agent.Langs.GetString( \"Profile.Warning.InvalidProfileName\" ), PackIconKind.CloseOctagon );\n            await DialogHost.Show( view, \"ProfileDialog\" );\n            return;\n        }\n\n        CreateProfile( newProfileName );\n    }\n\n    private void CreateProfile( string profileName )\n    {\n        var newProfile   = Manager.CurrentProfile.Clone();\n        var currentRules = Conditions.FetchRules();\n\n        Manager.Configs.Profiles.Add( profileName, newProfile );\n        Manager.Configs.CurrentProfileName = profileName;\n        Manager.Save( reason: \"Create\", reasonName: \"Profile\" );\n\n        Manager.SaveCluster( Manager.Configs.Cluster ); // save cluster for new profile\n        Conditions.SaveRules( currentRules ); // save rules for new profile\n\n        RulesViewModel.ReloadRules();\n\n        var vm = DataContext as SettingsViewModel;\n        vm.ProfileList.Add( new {Value = profileName} );\n        vm.CurrentProfile = profileName;\n    }\n\n    private async void ProfileRename_OnClick( object sender, RoutedEventArgs e )\n    {\n        if ( Manager.Configs.Profiles.Count == 1 )\n        {\n            var view = new YesNoWithNote( Agent.Langs.GetString( \"Profile.Warning.LastProfileProtect\" ), PackIconKind.CloseOctagon );\n            await DialogHost.Show( view, \"ProfileDialog\" );\n            return;\n        }\n\n        var pndView = new ProfileNameDialog( cbbProfiles.Text );\n        await DialogHost.Show( pndView, \"ProfileDialog\", null, ClosingEventHandler, null );\n    }\n\n    private async void ProfileRemove_OnClick( object sender, RoutedEventArgs e )\n    {\n        YesNoWithNote view;\n        if ( Manager.Configs.Profiles.Count == 1 )\n        {\n            view = new YesNoWithNote( Agent.Langs.GetString( \"Profile.Warning.LastProfileProtect\" ), PackIconKind.CloseOctagon );\n            await DialogHost.Show( view, \"ProfileDialog\" );\n            return;\n        }\n\n        view = new YesNoWithNote( Agent.Langs.GetString( \"Profile.Confirm.Delete\" ), PackIconKind.Warning );\n        var result = await DialogHost.Show( view, \"ProfileDialog\" );\n        if ( result is false ) return;\n\n        var delProfile = cbbProfiles.Text;\n\n        Manager.Configs.Profiles.Remove( delProfile );\n        Manager.Configs.CurrentProfileName = Manager.Configs.Profiles.Keys.Last();\n        Manager.Save( reason: \"Delete\", reasonName: \"Profile\" );\n        Manager.DeleteFilesOfProfile( delProfile );\n\n        var vm = DataContext as SettingsViewModel;\n        vm.CurrentProfile = Manager.Configs.CurrentProfileName;\n        vm.ProfileList.Remove( vm.ProfileList.First( x => ( (dynamic)x ).Value == delProfile ) );\n    }\n\n    private void ClosingEventHandler( object sender, DialogClosingEventArgs eventArgs )\n    {\n        eventArgs.Handled = true;\n        if ( eventArgs.Parameter is false ) return;\n\n        var pndView = eventArgs.Session.Content as ProfileNameDialog;\n        if ( pndView == null ) return;\n\n        var oldName = cbbProfiles.SelectedValue.ToString();\n\n        var newName = pndView.EditProfileName;\n        if ( newName == oldName ) return;\n\n        var isValid = !string.IsNullOrEmpty( newName ) &&\n                      newName.IndexOfAny( Path.GetInvalidFileNameChars() ) < 0 &&\n                      !File.Exists( Path.Combine( Manager.ProfileFolder, newName ) );\n\n        if ( Manager.Configs.Profiles.ContainsKey( newName ) || !isValid )\n        {\n            pndView.SetErrors( Agent.Langs.GetString( \"Profile.Warning.InvalidProfileName\" ) );\n            eventArgs.Cancel();\n            return;\n        }\n\n        CreateProfile( newName );\n\n        Manager.Configs.Profiles.Remove( oldName );\n        Manager.Save( reason: \"Delete\", reasonName: \"Profile\" );\n        Manager.DeleteFilesOfProfile( oldName );\n\n        var vm = DataContext as SettingsViewModel;\n        vm.ProfileList.Remove( vm.ProfileList.First( x => ( (dynamic)x ).Value == oldName ) );\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Pages/UI.xaml",
    "content": "﻿<UserControl x:Class=\"ControlPanel.Pages.UI\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n             xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n             xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n             xmlns:lex=\"http://wpflocalizeextension.codeplex.com\"\n             xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n             xmlns:commons=\"clr-namespace:ControlPanel.Pages.Menus.Commons\"\n             xmlns:converters=\"clr-namespace:ControlPanel.Converters\"\n             mc:Ignorable=\"d\">\n\n    <UserControl.Resources>\n        <ResourceDictionary>\n            <Style TargetType=\"GroupBox\" BasedOn=\"{StaticResource MaterialDesignGroupBox}\">\n                <Setter Property=\"HeaderTemplate\">\n                    <Setter.Value>\n                        <DataTemplate>\n                            <TextBlock Foreground=\"{DynamicResource MaterialDesignBody}\" Text=\"{Binding}\" FontWeight=\"Bold\" FontSize=\"20\" />\n                        </DataTemplate>\n                    </Setter.Value>\n                </Setter>\n            </Style>\n            <converters:UIButtonStyleByVdAConverter x:Key=\"UIButtonStyleByVdAConverter\" />\n            <converters:CheckBoxConverter x:Key=\"CheckBoxConverter\" />\n        </ResourceDictionary>\n    </UserControl.Resources>\n\n    <Grid>\n        <Grid.RowDefinitions>\n            <RowDefinition Height=\"Auto\" />\n            <RowDefinition Height=\"*\" />\n        </Grid.RowDefinitions>\n\n        <commons:MenuContainer x:Name=\"MenuContainer\" Grid.Row=\"0\" />\n\n        <materialDesign:Card Grid.Row=\"1\" materialDesign:ElevationAssist.Elevation=\"Dp2\" Margin=\"10,10,10,12\">\n            <StackPanel>\n\n                <TextBlock FontSize=\"20\" Margin=\"10\" Text=\"{lex:Loc Page.UI.VdArrangement}\"></TextBlock>\n\n                <UniformGrid x:Name=\"ButtonsContainer\" Rows=\"2\" Columns=\"4\" Margin=\"0,10\">\n                    <UniformGrid.Resources>\n                        <Style TargetType=\"Button\">\n                            <Style.Resources>\n                                <Style TargetType=\"Border\">\n                                    <Setter Property=\"CornerRadius\" Value=\"5\" />\n                                </Style>\n                            </Style.Resources>\n                            <!-- <Style.Triggers> -->\n                            <!--     <Trigger Property=\"IsEnabled\" Value=\"False\"> -->\n                            <!--         <Setter Property=\"Template\"> -->\n                            <!--             <Setter.Value> -->\n                            <!--                 <ControlTemplate TargetType=\"{x:Type Button}\"> -->\n                            <!--                     <Grid Background=\"DimGray\"> -->\n                            <!--                         <ContentPresenter x:Name=\"MyContentPresenter\" -->\n                            <!--                                           Content=\"{TemplateBinding Content}\" -->\n                            <!--                                           HorizontalAlignment=\"Center\" -->\n                            <!--                                           VerticalAlignment=\"Center\" /> -->\n                            <!--                     </Grid> -->\n                            <!--                 </ControlTemplate> -->\n                            <!--             </Setter.Value> -->\n                            <!--         </Setter> -->\n                            <!--     </Trigger> -->\n                            <!-- </Style.Triggers> -->\n                            <!-- <Setter Property=\"IsEnabled\"> -->\n                            <!--     <Setter.Value> -->\n                            <!--         <MultiBinding Converter=\"{StaticResource UIButtonStyleByVdAConverter}\" Mode=\"OneWay\" ConverterParameter=\"C\"> -->\n                            <!--             <Binding Path=\"VdCount\" /> -->\n                            <!--             <Binding Path=\"Tag\" RelativeSource=\"{RelativeSource Self}\" /> -->\n                            <!--         </MultiBinding> -->\n                            <!--     </Setter.Value> -->\n                            <!-- </Setter> -->\n                            <Setter Property=\"Background\">\n                                <Setter.Value>\n                                    <MultiBinding Converter=\"{StaticResource UIButtonStyleByVdAConverter}\" Mode=\"OneWay\" ConverterParameter=\"B\">\n                                        <Binding Path=\"VdArrangement\" />\n                                        <Binding Path=\"Tag\" RelativeSource=\"{RelativeSource Self}\" />\n                                    </MultiBinding>\n                                </Setter.Value>\n                            </Setter>\n                        </Style>\n                        <Style TargetType=\"TextBlock\">\n                            <Setter Property=\"HorizontalAlignment\" Value=\"Center\"></Setter>\n                            <Setter Property=\"FontSize\" Value=\"11\"></Setter>\n                            <Setter Property=\"Margin\" Value=\"0,2,0,15\"></Setter>\n                        </Style>\n                    </UniformGrid.Resources>\n                    <StackPanel>\n                        <Button Width=\"128\" Height=\"128\" Tag=\"0\">\n                            <StaticResource ResourceKey=\"M0\" />\n                        </Button>\n                        <TextBlock Text=\"{lex:Loc Page.UI.Label.m0}\" />\n                    </StackPanel>\n                    <StackPanel>\n                        <Button Width=\"128\" Height=\"128\" Tag=\"1\">\n                            <StaticResource ResourceKey=\"M1\" />\n                        </Button>\n                        <TextBlock Text=\"{lex:Loc Page.UI.Label.m1}\" />\n                    </StackPanel>\n                    <StackPanel>\n                        <Button Width=\"128\" Height=\"128\" Tag=\"2\">\n                            <StaticResource ResourceKey=\"M2\" />\n                        </Button>\n                        <TextBlock Text=\"{lex:Loc Page.UI.Label.m2}\" />\n                    </StackPanel>\n                    <StackPanel>\n                        <Button Width=\"128\" Height=\"128\" Tag=\"3\">\n                            <StaticResource ResourceKey=\"M3\" />\n                        </Button>\n                        <TextBlock Text=\"{lex:Loc Page.UI.Label.m3}\" />\n                    </StackPanel>\n                    <StackPanel>\n                        <Button Width=\"128\" Height=\"128\" Tag=\"4\">\n                            <StaticResource ResourceKey=\"M4\" />\n                        </Button>\n                        <TextBlock Text=\"{lex:Loc Page.UI.Label.m4}\" />\n                    </StackPanel>\n                    <StackPanel>\n                        <Button Width=\"128\" Height=\"128\" Tag=\"5\">\n                            <StaticResource ResourceKey=\"M5\" />\n                        </Button>\n                        <TextBlock Text=\"{lex:Loc Page.UI.Label.m5}\" />\n                    </StackPanel>\n                    <StackPanel>\n                        <Button Width=\"128\" Height=\"128\" Tag=\"6\">\n                            <StaticResource ResourceKey=\"M6\" />\n                        </Button>\n                        <TextBlock Text=\"{lex:Loc Page.UI.Label.m6}\" />\n                    </StackPanel>\n                    <StackPanel>\n                        <Button Width=\"128\" Height=\"128\" Tag=\"7\">\n                            <StaticResource ResourceKey=\"M7\" />\n                        </Button>\n                        <TextBlock Text=\"{lex:Loc Page.UI.Label.m7}\" />\n                    </StackPanel>\n                </UniformGrid>\n\n                <!-- <materialDesign:Chip Height=\"50\" Margin=\"10,0\" Content=\"{lex:Loc Note.DesktopArrangement}\" /> -->\n\n                <Rectangle Height=\"1\" Margin=\"0,10\" Fill=\"{DynamicResource MaterialDesignDivider}\" />\n\n                <TextBlock FontSize=\"20\" Margin=\"10\" Text=\"{lex:Loc Page.UI.VdView}\"></TextBlock>\n\n                <Grid>\n                    <Grid.RowDefinitions>\n                        <RowDefinition></RowDefinition>\n                        <RowDefinition></RowDefinition>\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"Auto\"></ColumnDefinition>\n                        <ColumnDefinition Width=\"Auto\"></ColumnDefinition>\n                    </Grid.ColumnDefinitions>\n                    <CheckBox Content=\"{lex:Loc Page.UI.ShowVdName}\" Margin=\"10\"\n                              IsChecked=\"{Binding ShowVdName}\">\n                    </CheckBox>\n                    <CheckBox Content=\"{lex:Loc Page.UI.ShowVdIndex}\" Grid.Row=\"1\" Grid.Column=\"0\" Margin=\"10\"\n                              IsChecked=\"{Binding ShowVdIndex}\">\n                    </CheckBox>\n                    <StackPanel Orientation=\"Horizontal\" Grid.Row=\"1\" Grid.Column=\"1\">\n                        <RadioButton Content=\"{lex:Loc Page.UI.ShowVdIndex.ZeroBased}\" Margin=\"10,0\"\n                                     IsChecked=\"{Binding ShowVdIndexType,Converter={StaticResource CheckBoxConverter},ConverterParameter=0}\">\n                        </RadioButton>\n                        <RadioButton Content=\"{lex:Loc Page.UI.ShowVdIndex.OneBased}\" Margin=\"10,0\"\n                                     IsChecked=\"{Binding ShowVdIndexType,Converter={StaticResource CheckBoxConverter},ConverterParameter=1}\">\n                        </RadioButton>\n                    </StackPanel>\n                </Grid>\n\n            </StackPanel>\n\n        </materialDesign:Card>\n    </Grid>\n</UserControl>"
  },
  {
    "path": "WPF/ControlPanel/Pages/UI.xaml.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System.Windows;\nusing System.Windows.Controls;\nusing ControlPanel.ViewModels;\nusing MaterialDesignThemes.Wpf;\nusing VirtualSpace.Helpers;\n\nnamespace ControlPanel.Pages;\n\npublic partial class UI\n{\n    private static UI?         _instance;\n    private static UIViewModel _vm;\n\n    public UI()\n    {\n        InitializeComponent();\n    }\n\n    private UI( string headerKey, PackIconKind iconKind ) : this()\n    {\n        var mdc = (MenuContainerViewModel)MenuContainer.DataContext;\n        mdc.HeaderKey = headerKey;\n        mdc.IconKind = iconKind;\n        _vm = new UIViewModel();\n        DataContext = _vm;\n        ButtonsContainer.AddHandler( Button.ClickEvent, new RoutedEventHandler( OnVdArrangementButtonClicked ) );\n    }\n\n    private static void OnVdArrangementButtonClicked( object sender, RoutedEventArgs e )\n    {\n        var btn = (Button)e.OriginalSource;\n\n        _vm.VdArrangement = int.Parse( btn.Tag.ToString() );\n\n        User32.PostMessage( MainWindow.MainWindowHandle, WinMsg.WM_HOTKEY, UserMessage.DesktopArrangement, 0 );\n\n        e.Handled = true;\n    }\n\n    public static UI Create( string headerKey, PackIconKind iconKind )\n    {\n        return _instance ??= new UI( headerKey, iconKind );\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Pages/UserControls/RuleForm.xaml",
    "content": "﻿<UserControl x:Class=\"ControlPanel.Pages.UserControls.RuleForm\"\n             xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n             xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n             xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n             xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n             xmlns:lex=\"http://wpflocalizeextension.codeplex.com\"\n             xmlns:validation=\"clr-namespace:ControlPanel.Validation\"\n             xmlns:converters=\"clr-namespace:ControlPanel.Converters\"\n             xmlns:models=\"clr-namespace:ControlPanel.ViewModels\"\n             mc:Ignorable=\"d\"\n             d:DesignHeight=\"768\" d:DesignWidth=\"1024\">\n\n    <UserControl.Resources>\n        <ResourceDictionary>\n            <Style TargetType=\"Button\" BasedOn=\"{StaticResource MaterialDesignPaperSecondaryLightButton}\">\n                <Setter Property=\"Margin\" Value=\"10,5\" />\n                <Setter Property=\"Height\" Value=\"50\" />\n            </Style>\n            <converters:RuleFieldConverter x:Key=\"RuleFieldConverter\" />\n            <converters:RuleFieldFromControlNameConverter x:Key=\"RuleFieldFromControlNameConverter\" />\n            <converters:CheckBoxStateByIndexConverter x:Key=\"CheckBoxStateByIndexConverter\" />\n            <converters:RuleFormDefaultValueConverter x:Key=\"RuleFormDefaultValueConverter\" />\n            <converters:LocConverter x:Key=\"LocConverter\" />\n        </ResourceDictionary>\n    </UserControl.Resources>\n\n    <Grid x:Name=\"RuleDefBox\">\n        <Grid.Resources>\n            <Style TargetType=\"TextBox\" BasedOn=\"{StaticResource MaterialDesignTextBox}\">\n                <Setter Property=\"Margin\" Value=\"0,0,10,0\"></Setter>\n                <Setter Property=\"Padding\" Value=\"0\"></Setter>\n            </Style>\n        </Grid.Resources>\n        <Grid.RowDefinitions>\n            <RowDefinition></RowDefinition>\n            <RowDefinition MinHeight=\"60\" Height=\"Auto\"></RowDefinition>\n        </Grid.RowDefinitions>\n\n        <Grid>\n            <Grid.RowDefinitions>\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n            </Grid.RowDefinitions>\n\n            <Grid x:Name=\"GridBasic\">\n                <Grid.RowDefinitions>\n                    <RowDefinition />\n                    <RowDefinition />\n                </Grid.RowDefinitions>\n\n                <DockPanel LastChildFill=\"False\">\n                    <TextBlock Style=\"{StaticResource MaterialDesignHeadline5TextBlock}\" Text=\"{lex:Loc Page.Rules.Rule.Basic}\" />\n                    <StackPanel DockPanel.Dock=\"Right\" x:Name=\"RuleDate\" Width=\"210\" Margin=\"10,0\">\n                        <StackPanel Orientation=\"Horizontal\">\n                            <Label Content=\"{lex:Loc Page.Rules.Rule.Created}\" Padding=\"0\"\n                                   VerticalAlignment=\"Center\" MinWidth=\"80\" />\n                            <TextBlock VerticalAlignment=\"Center\" Text=\"{Binding Created,StringFormat={}{0:yyyy-MM-dd HH:mm:ss}}\" />\n                        </StackPanel>\n                        <StackPanel Orientation=\"Horizontal\">\n                            <Label Content=\"{lex:Loc Page.Rules.Rule.Updated}\" Padding=\"0\"\n                                   VerticalAlignment=\"Center\" MinWidth=\"80\" />\n                            <TextBlock VerticalAlignment=\"Center\" Text=\"{Binding Updated,StringFormat={}{0:yyyy-MM-dd HH:mm:ss}}\" />\n                        </StackPanel>\n                    </StackPanel>\n                </DockPanel>\n\n                <Grid Grid.Row=\"1\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition Height=\"Auto\" />\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"*\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                    </Grid.ColumnDefinitions>\n                    <DockPanel>\n                        <TextBox x:Name=\"tbWeight\"\n                                 DockPanel.Dock=\"Right\"\n                                 MinWidth=\"100\" FontSize=\"14\" Margin=\"10 0\"\n                                 materialDesign:HintAssist.FloatingScale=\"0.80\"\n                                 materialDesign:HintAssist.Hint=\"{lex:Loc Page.Rules.Weight}\"\n                                 materialDesign:TextFieldAssist.TextBoxViewMargin=\"1 0 1 0\"\n                                 Style=\"{StaticResource MaterialDesignFloatingHintTextBox}\">\n                            <TextBox.Text>\n                                <Binding Path=\"Weight\" UpdateSourceTrigger=\"Explicit\">\n                                    <Binding.ValidationRules>\n                                        <validation:NumberRangeValidationRule Min=\"1\" Max=\"100\" ValidatesOnTargetUpdated=\"True\" />\n                                    </Binding.ValidationRules>\n                                </Binding>\n                            </TextBox.Text>\n                        </TextBox>\n                        <TextBox DockPanel.Dock=\"Right\"\n                                 MinWidth=\"150\" FontSize=\"14\" Margin=\"20 0 10 0\"\n                                 materialDesign:HintAssist.FloatingScale=\"0.80\"\n                                 materialDesign:HintAssist.Hint=\"{lex:Loc Page.Rules.Rule.Tag}\"\n                                 materialDesign:TextFieldAssist.TextBoxViewMargin=\"1 0 1 0\"\n                                 Style=\"{StaticResource MaterialDesignFloatingHintTextBox}\"\n                                 Text=\"{Binding Tag, UpdateSourceTrigger=PropertyChanged}\">\n                        </TextBox>\n                        <TextBox x:Name=\"tbName\"\n                                 MinWidth=\"400\" FontSize=\"14\"\n                                 materialDesign:HintAssist.FloatingScale=\"0.80\"\n                                 materialDesign:HintAssist.Hint=\"{lex:Loc Generic.Name}\"\n                                 materialDesign:TextFieldAssist.TextBoxViewMargin=\"1 0 1 0\"\n                                 Style=\"{StaticResource MaterialDesignFloatingHintTextBox}\">\n                            <TextBox.Text>\n                                <Binding Path=\"Name\" UpdateSourceTrigger=\"Explicit\">\n                                    <Binding.ValidationRules>\n                                        <validation:NotEmptyValidationRule ValidatesOnTargetUpdated=\"False\" />\n                                    </Binding.ValidationRules>\n                                </Binding>\n                            </TextBox.Text>\n                        </TextBox>\n                    </DockPanel>\n\n                    <StackPanel Grid.Column=\"1\" Grid.Row=\"0\" Orientation=\"Horizontal\">\n                        <Label Content=\"{lex:Loc Page.Rules.Rule.Enabled}\" VerticalAlignment=\"Center\" />\n                        <ToggleButton Width=\"55\" Margin=\"10\" IsChecked=\"{Binding Enabled}\" />\n                    </StackPanel>\n                </Grid>\n            </Grid><!-- GridBasic -->\n\n            <Grid Grid.Column=\"0\" Grid.Row=\"1\" x:Name=\"GridWindowRules\">\n                <Grid.RowDefinitions>\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                </Grid.RowDefinitions>\n                <Grid.ColumnDefinitions>\n                    <ColumnDefinition MinWidth=\"100\" Width=\"Auto\" />\n                    <ColumnDefinition MinWidth=\"150\" Width=\"Auto\" />\n                    <ColumnDefinition Width=\"*\" />\n                </Grid.ColumnDefinitions>\n\n                <TextBlock Margin=\"0 15 0 0\" Style=\"{StaticResource MaterialDesignHeadline5TextBlock}\" Text=\"{lex:Loc Page.Rules.Rule.WindowRules}\" />\n\n                <CheckBox x:Name=\"chb_Title\" Grid.Row=\"1\" Grid.Column=\"0\" Margin=\"0,0,0,5\"\n                          Content=\"{lex:Loc Page.Rules.Rule.Title}\" VerticalAlignment=\"Bottom\">\n                    <CheckBox.IsChecked>\n                        <MultiBinding Converter=\"{StaticResource RuleFieldConverter}\" Mode=\"OneWay\" ConverterParameter=\"{x:Type CheckBox}\">\n                            <Binding Path=\"Expression\" />\n                            <Binding Path=\"Name\" RelativeSource=\"{RelativeSource Self}\" Converter=\"{StaticResource RuleFieldFromControlNameConverter}\" />\n                        </MultiBinding>\n                    </CheckBox.IsChecked>\n                </CheckBox>\n                <ComboBox x:Name=\"cbb_Title\" Grid.Row=\"1\" Grid.Column=\"1\"\n                          VerticalAlignment=\"Bottom\" Margin=\"20,0\"\n                          IsEnabled=\"{Binding IsChecked, ElementName=chb_Title}\"\n                          ItemsSource=\"{Binding Path=(models:RulesViewModel.Operators)}\"\n                          SelectedValuePath=\"Value\"\n                          SelectionChanged=\"Cbb_OnSelectionChanged\">\n                    <ComboBox.ItemTemplate>\n                        <DataTemplate>\n                            <TextBlock\n                                Text=\"{lex:Loc {Binding Value, Mode=OneWay,\n                                                Converter={StaticResource LocConverter},ConverterParameter=Page.Rules.Rule.Op.}}\" />\n                        </DataTemplate>\n                    </ComboBox.ItemTemplate>\n                    <ComboBox.SelectedIndex>\n                        <MultiBinding Converter=\"{StaticResource RuleFieldConverter}\" Mode=\"OneWay\" ConverterParameter=\"{x:Type ComboBox}\">\n                            <Binding Path=\"Expression\" />\n                            <Binding Path=\"Name\" RelativeSource=\"{RelativeSource Self}\" Converter=\"{StaticResource RuleFieldFromControlNameConverter}\" />\n                        </MultiBinding>\n                    </ComboBox.SelectedIndex>\n                </ComboBox>\n                <TextBox x:Name=\"tb_Title\" Grid.Row=\"1\" Grid.Column=\"2\" FontSize=\"14\"\n                         IsEnabled=\"{Binding IsChecked, ElementName=chb_Title}\">\n                    <TextBox.Text>\n                        <MultiBinding Converter=\"{StaticResource RuleFieldConverter}\" Mode=\"OneWay\" ConverterParameter=\"{x:Type TextBox}\">\n                            <Binding Path=\"Expression\" />\n                            <Binding Path=\"Name\" RelativeSource=\"{RelativeSource Self}\" Converter=\"{StaticResource RuleFieldFromControlNameConverter}\" />\n                        </MultiBinding>\n                    </TextBox.Text>\n                </TextBox>\n\n                <CheckBox x:Name=\"chb_ProcessName\" Grid.Row=\"2\" Grid.Column=\"0\" Margin=\"0,0,0,5\"\n                          Content=\"{lex:Loc Page.Rules.Rule.ProcessName}\" VerticalAlignment=\"Bottom\">\n                    <CheckBox.IsChecked>\n                        <MultiBinding Converter=\"{StaticResource RuleFieldConverter}\" Mode=\"OneWay\" ConverterParameter=\"{x:Type CheckBox}\">\n                            <Binding Path=\"Expression\" />\n                            <Binding Path=\"Name\" RelativeSource=\"{RelativeSource Self}\" Converter=\"{StaticResource RuleFieldFromControlNameConverter}\" />\n                        </MultiBinding>\n                    </CheckBox.IsChecked>\n                </CheckBox>\n                <ComboBox x:Name=\"cbb_ProcessName\" Grid.Row=\"2\" Grid.Column=\"1\"\n                          VerticalAlignment=\"Bottom\" Margin=\"20,0\"\n                          IsEnabled=\"{Binding IsChecked, ElementName=chb_ProcessName}\"\n                          ItemsSource=\"{Binding Path=(models:RulesViewModel.Operators)}\"\n                          SelectedValuePath=\"Value\"\n                          SelectionChanged=\"Cbb_OnSelectionChanged\">\n                    <ComboBox.ItemTemplate>\n                        <DataTemplate>\n                            <TextBlock\n                                Text=\"{lex:Loc {Binding Value, Mode=OneWay,\n                                                Converter={StaticResource LocConverter},ConverterParameter=Page.Rules.Rule.Op.}}\" />\n                        </DataTemplate>\n                    </ComboBox.ItemTemplate>\n                    <ComboBox.SelectedIndex>\n                        <MultiBinding Converter=\"{StaticResource RuleFieldConverter}\" Mode=\"OneWay\" ConverterParameter=\"{x:Type ComboBox}\">\n                            <Binding Path=\"Expression\" />\n                            <Binding Path=\"Name\" RelativeSource=\"{RelativeSource Self}\" Converter=\"{StaticResource RuleFieldFromControlNameConverter}\" />\n                        </MultiBinding>\n                    </ComboBox.SelectedIndex>\n                </ComboBox>\n                <TextBox x:Name=\"tb_ProcessName\" Grid.Row=\"2\" Grid.Column=\"2\" FontSize=\"14\"\n                         IsEnabled=\"{Binding IsChecked, ElementName=chb_ProcessName}\">\n                    <TextBox.Text>\n                        <MultiBinding Converter=\"{StaticResource RuleFieldConverter}\" Mode=\"OneWay\" ConverterParameter=\"{x:Type TextBox}\">\n                            <Binding Path=\"Expression\" />\n                            <Binding Path=\"Name\" RelativeSource=\"{RelativeSource Self}\" Converter=\"{StaticResource RuleFieldFromControlNameConverter}\" />\n                        </MultiBinding>\n                    </TextBox.Text>\n                </TextBox>\n\n                <CheckBox x:Name=\"chb_ProcessPath\" Grid.Row=\"3\" Grid.Column=\"0\" Margin=\"0,0,0,5\"\n                          Content=\"{lex:Loc Page.Rules.Rule.ProcessPath}\" VerticalAlignment=\"Bottom\">\n                    <CheckBox.IsChecked>\n                        <MultiBinding Converter=\"{StaticResource RuleFieldConverter}\" Mode=\"OneWay\" ConverterParameter=\"{x:Type CheckBox}\">\n                            <Binding Path=\"Expression\" />\n                            <Binding Path=\"Name\" RelativeSource=\"{RelativeSource Self}\" Converter=\"{StaticResource RuleFieldFromControlNameConverter}\" />\n                        </MultiBinding>\n                    </CheckBox.IsChecked>\n                </CheckBox>\n                <ComboBox x:Name=\"cbb_ProcessPath\" Grid.Row=\"3\" Grid.Column=\"1\"\n                          VerticalAlignment=\"Bottom\" Margin=\"20,0\"\n                          IsEnabled=\"{Binding IsChecked, ElementName=chb_ProcessPath}\"\n                          ItemsSource=\"{Binding Path=(models:RulesViewModel.Operators)}\"\n                          SelectedValuePath=\"Value\"\n                          SelectionChanged=\"Cbb_OnSelectionChanged\">\n                    <ComboBox.ItemTemplate>\n                        <DataTemplate>\n                            <TextBlock\n                                Text=\"{lex:Loc {Binding Value, Mode=OneWay,\n                                                Converter={StaticResource LocConverter},ConverterParameter=Page.Rules.Rule.Op.}}\" />\n                        </DataTemplate>\n                    </ComboBox.ItemTemplate>\n                    <ComboBox.SelectedIndex>\n                        <MultiBinding Converter=\"{StaticResource RuleFieldConverter}\" Mode=\"OneWay\" ConverterParameter=\"{x:Type ComboBox}\">\n                            <Binding Path=\"Expression\" />\n                            <Binding Path=\"Name\" RelativeSource=\"{RelativeSource Self}\" Converter=\"{StaticResource RuleFieldFromControlNameConverter}\" />\n                        </MultiBinding>\n                    </ComboBox.SelectedIndex>\n                </ComboBox>\n                <TextBox x:Name=\"tb_ProcessPath\" Grid.Row=\"3\" Grid.Column=\"2\" FontSize=\"14\"\n                         IsEnabled=\"{Binding IsChecked, ElementName=chb_ProcessPath}\">\n                    <TextBox.Text>\n                        <MultiBinding Converter=\"{StaticResource RuleFieldConverter}\" Mode=\"OneWay\" ConverterParameter=\"{x:Type TextBox}\">\n                            <Binding Path=\"Expression\" />\n                            <Binding Path=\"Name\" RelativeSource=\"{RelativeSource Self}\" Converter=\"{StaticResource RuleFieldFromControlNameConverter}\" />\n                        </MultiBinding>\n                    </TextBox.Text>\n                </TextBox>\n\n                <CheckBox x:Name=\"chb_CommandLine\" Grid.Row=\"4\" Grid.Column=\"0\" Margin=\"0,0,0,5\"\n                          Content=\"{lex:Loc Page.Rules.Rule.CommandLine}\" VerticalAlignment=\"Bottom\">\n                    <CheckBox.IsChecked>\n                        <MultiBinding Converter=\"{StaticResource RuleFieldConverter}\" Mode=\"OneWay\" ConverterParameter=\"{x:Type CheckBox}\">\n                            <Binding Path=\"Expression\" />\n                            <Binding Path=\"Name\" RelativeSource=\"{RelativeSource Self}\" Converter=\"{StaticResource RuleFieldFromControlNameConverter}\" />\n                        </MultiBinding>\n                    </CheckBox.IsChecked>\n                </CheckBox>\n                <ComboBox x:Name=\"cbb_CommandLine\" Grid.Row=\"4\" Grid.Column=\"1\"\n                          VerticalAlignment=\"Bottom\" Margin=\"20,0\"\n                          IsEnabled=\"{Binding IsChecked, ElementName=chb_CommandLine}\"\n                          ItemsSource=\"{Binding Path=(models:RulesViewModel.Operators)}\"\n                          SelectedValuePath=\"Value\"\n                          SelectionChanged=\"Cbb_OnSelectionChanged\">\n                    <ComboBox.ItemTemplate>\n                        <DataTemplate>\n                            <TextBlock\n                                Text=\"{lex:Loc {Binding Value, Mode=OneWay,\n                                                Converter={StaticResource LocConverter},ConverterParameter=Page.Rules.Rule.Op.}}\" />\n                        </DataTemplate>\n                    </ComboBox.ItemTemplate>\n                    <ComboBox.SelectedIndex>\n                        <MultiBinding Converter=\"{StaticResource RuleFieldConverter}\" Mode=\"OneWay\" ConverterParameter=\"{x:Type ComboBox}\">\n                            <Binding Path=\"Expression\" />\n                            <Binding Path=\"Name\" RelativeSource=\"{RelativeSource Self}\" Converter=\"{StaticResource RuleFieldFromControlNameConverter}\" />\n                        </MultiBinding>\n                    </ComboBox.SelectedIndex>\n                </ComboBox>\n                <TextBox x:Name=\"tb_CommandLine\" Grid.Row=\"4\" Grid.Column=\"2\" FontSize=\"14\"\n                         IsEnabled=\"{Binding IsChecked, ElementName=chb_CommandLine}\">\n                    <TextBox.Text>\n                        <MultiBinding Converter=\"{StaticResource RuleFieldConverter}\" Mode=\"OneWay\" ConverterParameter=\"{x:Type TextBox}\">\n                            <Binding Path=\"Expression\" />\n                            <Binding Path=\"Name\" RelativeSource=\"{RelativeSource Self}\" Converter=\"{StaticResource RuleFieldFromControlNameConverter}\" />\n                        </MultiBinding>\n                    </TextBox.Text>\n                </TextBox>\n\n                <CheckBox x:Name=\"chb_WndClass\" Grid.Row=\"5\" Grid.Column=\"0\" Margin=\"0,0,0,5\"\n                          Content=\"{lex:Loc Page.Rules.Rule.WndClass}\" VerticalAlignment=\"Bottom\">\n                    <CheckBox.IsChecked>\n                        <MultiBinding Converter=\"{StaticResource RuleFieldConverter}\" Mode=\"OneWay\" ConverterParameter=\"{x:Type CheckBox}\">\n                            <Binding Path=\"Expression\" />\n                            <Binding Path=\"Name\" RelativeSource=\"{RelativeSource Self}\" Converter=\"{StaticResource RuleFieldFromControlNameConverter}\" />\n                        </MultiBinding>\n                    </CheckBox.IsChecked>\n                </CheckBox>\n                <ComboBox x:Name=\"cbb_WndClass\" Grid.Row=\"5\" Grid.Column=\"1\"\n                          VerticalAlignment=\"Bottom\"\n                          IsEnabled=\"{Binding IsChecked, ElementName=chb_WndClass}\" Margin=\"20,0\"\n                          ItemsSource=\"{Binding Path=(models:RulesViewModel.Operators)}\"\n                          SelectedValuePath=\"Value\"\n                          SelectionChanged=\"Cbb_OnSelectionChanged\">\n                    <ComboBox.ItemTemplate>\n                        <DataTemplate>\n                            <TextBlock\n                                Text=\"{lex:Loc {Binding Value, Mode=OneWay,\n                                                Converter={StaticResource LocConverter},ConverterParameter=Page.Rules.Rule.Op.}}\" />\n                        </DataTemplate>\n                    </ComboBox.ItemTemplate>\n                    <ComboBox.SelectedIndex>\n                        <MultiBinding Converter=\"{StaticResource RuleFieldConverter}\" Mode=\"OneWay\" ConverterParameter=\"{x:Type ComboBox}\">\n                            <Binding Path=\"Expression\" />\n                            <Binding Path=\"Name\" RelativeSource=\"{RelativeSource Self}\" Converter=\"{StaticResource RuleFieldFromControlNameConverter}\" />\n                        </MultiBinding>\n                    </ComboBox.SelectedIndex>\n                </ComboBox>\n                <TextBox x:Name=\"tb_WndClass\" Grid.Row=\"5\" Grid.Column=\"2\" FontSize=\"14\"\n                         IsEnabled=\"{Binding IsChecked, ElementName=chb_WndClass}\">\n                    <TextBox.Text>\n                        <MultiBinding Converter=\"{StaticResource RuleFieldConverter}\" Mode=\"OneWay\" ConverterParameter=\"{x:Type TextBox}\">\n                            <Binding Path=\"Expression\" />\n                            <Binding Path=\"Name\" RelativeSource=\"{RelativeSource Self}\" Converter=\"{StaticResource RuleFieldFromControlNameConverter}\" />\n                        </MultiBinding>\n                    </TextBox.Text>\n                </TextBox>\n\n                <CheckBox x:Name=\"chb_WinInScreen\" Grid.Row=\"6\" Grid.Column=\"0\"\n                          Content=\"{lex:Loc Page.Rules.Rule.WinInScreen}\" VerticalAlignment=\"Bottom\">\n                    <CheckBox.IsChecked>\n                        <MultiBinding Converter=\"{StaticResource RuleFieldConverter}\" Mode=\"OneWay\" ConverterParameter=\"{x:Type CheckBox}\">\n                            <Binding Path=\"Expression\" />\n                            <Binding Path=\"Name\" RelativeSource=\"{RelativeSource Self}\" Converter=\"{StaticResource RuleFieldFromControlNameConverter}\" />\n                        </MultiBinding>\n                    </CheckBox.IsChecked>\n                </CheckBox>\n                <ComboBox x:Name=\"cbb_WinInScreen\" Grid.Row=\"6\" Grid.Column=\"1\" Grid.ColumnSpan=\"2\"\n                          VerticalAlignment=\"Bottom\" Margin=\"20,0,10,0\"\n                          IsEnabled=\"{Binding IsChecked, ElementName=chb_WinInScreen}\"\n                          ItemsSource=\"{Binding Path=(models:RulesViewModel.Screens)}\"\n                          DisplayMemberPath=\"Text\" SelectedValuePath=\"Value\">\n                    <ComboBox.SelectedIndex>\n                        <MultiBinding Converter=\"{StaticResource RuleFieldConverter}\" Mode=\"OneWay\" ConverterParameter=\"V\">\n                            <Binding Path=\"Expression\" />\n                            <Binding Path=\"Name\" RelativeSource=\"{RelativeSource Self}\" Converter=\"{StaticResource RuleFieldFromControlNameConverter}\" />\n                        </MultiBinding>\n                    </ComboBox.SelectedIndex>\n                </ComboBox>\n\n            </Grid><!-- GridWindowRules -->\n\n            <Grid x:Name=\"GridWindowActions\" Grid.Row=\"2\">\n                <Grid.RowDefinitions>\n                    <RowDefinition />\n                    <RowDefinition />\n                </Grid.RowDefinitions>\n\n                <TextBlock Margin=\"0,10\" Style=\"{StaticResource MaterialDesignHeadline5TextBlock}\" Text=\"{lex:Loc Page.Rules.Rule.WindowActions}\" />\n\n                <Grid Grid.Row=\"1\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition></RowDefinition>\n                        <RowDefinition></RowDefinition>\n                        <RowDefinition></RowDefinition>\n                        <RowDefinition></RowDefinition>\n                        <RowDefinition></RowDefinition>\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition MinWidth=\"100\" Width=\"Auto\" />\n                        <ColumnDefinition MinWidth=\"300\" Width=\"Auto\" />\n                        <ColumnDefinition MinWidth=\"100\" Width=\"Auto\" />\n                    </Grid.ColumnDefinitions>\n\n                    <CheckBox x:Name=\"chb_MoveToDesktop\" Grid.Row=\"0\" Grid.Column=\"0\" Margin=\"0,0,0,5\"\n                              Content=\"{lex:Loc Page.Rules.Rule.MoveToDesktop}\" VerticalAlignment=\"Bottom\"\n                              IsChecked=\"{Binding Action.MoveToDesktop, Converter={StaticResource CheckBoxStateByIndexConverter}, Mode=OneWay}\">\n                    </CheckBox>\n                    <ComboBox x:Name=\"cbb_MoveToDesktop\" Grid.Row=\"0\" Grid.Column=\"1\"\n                              VerticalAlignment=\"Bottom\" Margin=\"20,0\"\n                              IsEnabled=\"{Binding IsChecked, ElementName=chb_MoveToDesktop}\"\n                              ItemsSource=\"{Binding Path=(models:RulesViewModel.Desktops)}\"\n                              DisplayMemberPath=\"Text\" SelectedValuePath=\"Value\"\n                              SelectedValue=\"{Binding Action.MoveToDesktop, Mode=OneWay, Converter={StaticResource RuleFormDefaultValueConverter}}\">\n                    </ComboBox>\n                    <CheckBox x:Name=\"chb_FollowWindow\" Grid.Row=\"0\" Grid.Column=\"2\" Margin=\"0,0,10,5\"\n                              IsEnabled=\"{Binding IsChecked, ElementName=chb_MoveToDesktop}\"\n                              Content=\"{lex:Loc Page.Rules.Rule.FollowWindow}\" VerticalAlignment=\"Bottom\"\n                              IsChecked=\"{Binding Action.FollowWindow, Mode=OneWay}\">\n                    </CheckBox>\n\n                    <CheckBox x:Name=\"chb_PinWindow\" Grid.Row=\"1\" Grid.Column=\"0\" Margin=\"0,5,0,5\"\n                              Content=\"{lex:Loc Page.Rules.Rule.PinWindow}\" VerticalAlignment=\"Bottom\"\n                              IsChecked=\"{Binding Action.PinWindow, Mode=OneWay}\">\n                    </CheckBox>\n\n                    <CheckBox x:Name=\"chb_PinApp\" Grid.Row=\"2\" Grid.Column=\"0\" Margin=\"0,5,0,5\"\n                              Content=\"{lex:Loc Page.Rules.Rule.PinApp}\" VerticalAlignment=\"Bottom\"\n                              IsChecked=\"{Binding Action.PinApp, Mode=OneWay}\">\n                    </CheckBox>\n\n                    <CheckBox x:Name=\"chb_HideFromView\" Grid.Row=\"3\" Grid.Column=\"0\" Margin=\"0,5,0,5\"\n                              Content=\"{lex:Loc Page.Rules.Rule.HideFromView}\" VerticalAlignment=\"Bottom\"\n                              IsChecked=\"{Binding Action.HideFromView, Mode=OneWay}\">\n                    </CheckBox>\n\n                    <CheckBox x:Name=\"chb_MoveToScreen\" Grid.Row=\"4\" Grid.Column=\"0\" Margin=\"0,5,0,0\"\n                              Content=\"{lex:Loc Page.Rules.Rule.MoveToScreen}\" VerticalAlignment=\"Bottom\"\n                              IsChecked=\"{Binding Action.MoveToScreen, Converter={StaticResource CheckBoxStateByIndexConverter}, Mode=OneWay}\">\n                    </CheckBox>\n                    <ComboBox x:Name=\"cbb_MoveToScreen\" Grid.Row=\"4\" Grid.Column=\"1\"\n                              VerticalAlignment=\"Bottom\" Margin=\"20,0\"\n                              IsEnabled=\"{Binding IsChecked, ElementName=chb_MoveToScreen}\"\n                              ItemsSource=\"{Binding Path=(models:RulesViewModel.Screens)}\"\n                              DisplayMemberPath=\"Text\" SelectedValuePath=\"Value\"\n                              SelectedValue=\"{Binding Action.MoveToScreen, Mode=OneWay, Converter={StaticResource RuleFormDefaultValueConverter}}\">\n                    </ComboBox>\n                </Grid>\n            </Grid><!-- GridWindowActions -->\n\n        </Grid>\n\n        <StackPanel Grid.Column=\"0\" Grid.Row=\"1\" x:Name=\"ButtonBar\" Orientation=\"Horizontal\" HorizontalAlignment=\"Right\">\n            <materialDesign:Snackbar HorizontalAlignment=\"Right\" Margin=\"10\" x:Name=\"Snackbar\" MessageQueue=\"{materialDesign:MessageQueue}\" />\n            <Button x:Name=\"btnSave\" IsDefault=\"True\"\n                    Margin=\"10\" Width=\"180\"\n                    VerticalAlignment=\"Center\" HorizontalAlignment=\"Center\"\n                    Content=\"{lex:Loc Page.Rules.Rule.Save}\" Click=\"BtnSave_OnClick\" />\n            <Button x:Name=\"btnCloseDefBox\" IsCancel=\"True\"\n                    Margin=\"10\" Width=\"120\"\n                    VerticalAlignment=\"Center\" HorizontalAlignment=\"Center\"\n                    Content=\"{lex:Loc Page.Rules.Rule.CloseDefBox}\" Click=\"BtnCloseDefBox_OnClick\" />\n        </StackPanel>\n    </Grid>\n\n</UserControl>"
  },
  {
    "path": "WPF/ControlPanel/Pages/UserControls/RuleForm.xaml.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text.Json;\nusing System.Windows;\nusing System.Windows.Controls;\nusing ControlPanel.Validation;\nusing ControlPanel.ViewModels;\nusing LinqExpressionBuilder;\nusing VirtualSpace;\nusing VirtualSpace.Config.Events.Entity;\nusing VirtualSpace.Config.Events.Expression;\nusing VirtualSpace.Helpers;\n\nnamespace ControlPanel.Pages.UserControls;\n\npublic partial class RuleForm : UserControl\n{\n    public RuleForm()\n    {\n        InitializeComponent();\n    }\n\n    public FullObservableCollection<RuleTemplate> RuleListItemsSource { get; set; }\n\n    private void Cbb_OnSelectionChanged( object sender, SelectionChangedEventArgs e )\n    {\n        if ( sender is not ComboBox {IsLoaded: true} cbb || cbb.SelectedValue is null ) return;\n\n        var field = cbb.Name.Split( \"_\" )[1]; // 依赖控件名，若修改控件名，此处也要修改\n\n        var r = RuleDefBox.DataContext as RuleTemplate;\n        if ( r?.Expression == null ) return;\n\n        var exp = Conditions.ParseExpressionTemplate( r.Expression );\n        foreach ( var rule in exp.rules.Where( rule => rule.field == field ) )\n        {\n            rule.@operator = cbb.SelectedValue.ToString();\n            break;\n        }\n\n        r.Expression = JsonDocument.Parse( JsonSerializer.Serialize( exp, RulesViewModel.WriteOptions ) );\n    }\n\n    private void BtnSave_OnClick( object sender, RoutedEventArgs e )\n    {\n        if ( Helper.HasError( TextBox.TextProperty, tbName, tbWeight ) ) goto FAIL;\n\n        var r = RuleDefBox.DataContext as RuleTemplate;\n\n        if ( chb_Title.IsChecked == false &&\n             chb_ProcessName.IsChecked == false &&\n             chb_ProcessPath.IsChecked == false &&\n             chb_CommandLine.IsChecked == false &&\n             chb_WinInScreen.IsChecked == false &&\n             chb_WndClass.IsChecked == false )\n        {\n            Snackbar.MessageQueue?.Enqueue(\n                Agent.Langs.GetString( \"Rule.AtLeastOne\" ),\n                null,\n                null,\n                null,\n                false,\n                true,\n                TimeSpan.FromSeconds( 5 ) );\n            goto FAIL;\n        }\n\n        var exp = new ExpressionTemplate\n        {\n            condition = Keywords.And,\n            rules = new List<ExpressionTemplate>(),\n        };\n\n        if ( r.Expression != null )\n        {\n            exp.id = Conditions.ParseExpressionTemplate( r.Expression ).id;\n        }\n\n        try\n        {\n            BuildRule( chb_Title, cbb_Title, tb_Title, exp );\n            BuildRule( chb_ProcessName, cbb_ProcessName, tb_ProcessName, exp );\n            BuildRule( chb_ProcessPath, cbb_ProcessPath, tb_ProcessPath, exp );\n            BuildRule( chb_CommandLine, cbb_CommandLine, tb_CommandLine, exp );\n            BuildRule( chb_WndClass, cbb_WndClass, tb_WndClass, exp );\n            BuildRule( chb_WinInScreen, cbb_WinInScreen, null, exp );\n        }\n        catch ( Exception ex )\n        {\n            Snackbar.MessageQueue?.Enqueue(\n                Agent.Langs.GetString( ex.Message ),\n                null,\n                null,\n                null,\n                false,\n                true,\n                TimeSpan.FromSeconds( 5 ) );\n            goto FAIL;\n        }\n\n        r.Expression = JsonDocument.Parse( JsonSerializer.Serialize( exp, RulesViewModel.WriteOptions ) );\n\n        var action = r.Action;\n        if ( chb_MoveToDesktop.IsChecked == true )\n        {\n            action.MoveToDesktop = int.Parse( cbb_MoveToDesktop.SelectedValue.ToString() );\n        }\n\n        action.FollowWindow = (bool)chb_FollowWindow.IsChecked;\n        action.PinWindow = (bool)chb_PinWindow.IsChecked;\n        action.PinApp = (bool)chb_PinApp.IsChecked;\n        action.HideFromView = (bool)chb_HideFromView.IsChecked;\n\n        if ( chb_MoveToScreen.IsChecked == true )\n        {\n            action.MoveToScreen = int.Parse( cbb_MoveToScreen.SelectedValue.ToString() );\n        }\n\n        if ( r.Id == Guid.Empty )\n        {\n            r.Id = Guid.NewGuid();\n            r.Created = DateTime.Now;\n            r.Updated = r.Created;\n            RuleListItemsSource.Add( r );\n        }\n        else\n        {\n            r.Updated = DateTime.Now;\n        }\n\n        return;\n\n        FAIL:\n        e.Handled = true;\n    }\n\n    private void BuildRule( CheckBox cb, ComboBox cbb, TextBox? tb, ExpressionTemplate exp )\n    {\n        if ( cb.IsChecked != true ) return;\n\n        var V   = new Value();\n        var opt = cbb.SelectedValue.ToString();\n        if ( tb is null )\n        {\n            opt = Keywords.Eq[0];\n            V = new Value {V = cbb.SelectedValue.ToString()};\n        }\n        else\n        {\n            if ( opt == Keywords.RegexIsMatch[0] && !StringHelper.IsValidRegex( tb.Text ) )\n            {\n                throw new Exception( \"Rule.InvalidRegex\" );\n            }\n\n            V = new Value {V = tb.Text};\n        }\n\n        var rule = new ExpressionTemplate\n        {\n            type = Keywords.String,\n            field = cb.Name.Split( \"_\" )[1],\n            @operator = opt,\n            value = V\n        };\n\n        exp.rules.Add( rule );\n    }\n\n    private void BtnCloseDefBox_OnClick( object sender, RoutedEventArgs e )\n    {\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Resources/Definitions/KeyboardTree.json",
    "content": "﻿{\n  \"Nodes\": [\n    {\n      \"Name\": \"K_G\",\n      \"Header\": \"K_G\",\n      \"Nodes\": [\n        {\n          \"Name\": \"hk_node_rise_mainview\",\n          \"Header\": \"hk_node_rise_mainview\"\n        },\n        {\n          \"Name\": \"hk_node_open_app_controller\",\n          \"Header\": \"hk_node_open_app_controller\"\n        },\n        {\n          \"Name\": \"hk_node_rise_mainview_for_active_app\",\n          \"Header\": \"hk_node_rise_mainview_for_active_app\"\n        },\n        {\n          \"Name\": \"hk_node_rise_mainview_for_current_vd\",\n          \"Header\": \"hk_node_rise_mainview_for_current_vd\"\n        },\n        {\n          \"Name\": \"hk_node_rise_mainview_for_active_app_in_current_vd\",\n          \"Header\": \"hk_node_rise_mainview_for_active_app_in_current_vd\"\n        },\n        {\n          \"Name\": \"hk_node_toggle_window_filter\",\n          \"Header\": \"hk_node_toggle_window_filter\",\n          \"IsHidden\": true\n        }\n      ]\n    },\n    {\n      \"Name\": \"K_D\",\n      \"Header\": \"K_D\",\n      \"Nodes\": [\n        {\n          \"Name\": \"K_D_S\",\n          \"Header\": \"K_D_S\"\n        },\n        {\n          \"Name\": \"K_D_N\",\n          \"Header\": \"K_D_N\",\n          \"Nodes\": [\n            {\n              \"Name\": \"hk_node_nav_left\",\n              \"Header\": \"hk_node_nav_left\"\n            },\n            {\n              \"Name\": \"hk_node_nav_right\",\n              \"Header\": \"hk_node_nav_right\"\n            },\n            {\n              \"Name\": \"hk_node_nav_up\",\n              \"Header\": \"hk_node_nav_up\"\n            },\n            {\n              \"Name\": \"hk_node_nav_down\",\n              \"Header\": \"hk_node_nav_down\"\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"Name\": \"K_W\",\n      \"Header\": \"K_W\",\n      \"Nodes\": [\n        {\n          \"Name\": \"K_W_M\",\n          \"Header\": \"K_W_M\"\n        },\n        {\n          \"Name\": \"K_W_MF\",\n          \"Header\": \"K_W_MF\"\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "WPF/ControlPanel/Resources/Definitions/MouseTree.json",
    "content": "﻿{\n  \"Nodes\": [\n    {\n      \"Header\": \"M.ROOT\",\n      \"Tag\": \"ROOT\",\n      \"Nodes\": [\n        {\n          \"Header\": \"M.D\",\n          \"Tag\": \"Desktop\",\n          \"Nodes\": [\n            {\n              \"Name\": \"DesktopVisibleAndCloseView\",\n              \"Header\": \"M.D.DesktopVisibleAndCloseView\",\n              \"Tag\": \"mouse_node_d_\"\n            },\n            {\n              \"Name\": \"DesktopVisibleOnly\",\n              \"Header\": \"M.D.DesktopVisibleOnly\",\n              \"Tag\": \"mouse_node_d_\"\n            },\n            {\n              \"Name\": \"ContextMenu\",\n              \"Header\": \"M.ContextMenu\",\n              \"Tag\": \"mouse_node_d_\"\n            },\n            {\n              \"Name\": \"DesktopShowForSelectedDesktop\",\n              \"Header\": \"M.D.DesktopShowForSelectedDesktop\",\n              \"Tag\": \"mouse_node_d_\"\n            }\n          ]\n        },\n        {\n          \"Header\": \"M.W\",\n          \"Tag\": \"Window\",\n          \"Nodes\": [\n            {\n              \"Name\": \"WindowActiveDesktopVisibleAndCloseView\",\n              \"Header\": \"M.W.WindowActiveDesktopVisibleAndCloseView\",\n              \"Tag\": \"mouse_node_w_\"\n            },\n            {\n              \"Name\": \"WindowActiveDesktopVisibleOnly\",\n              \"Header\": \"M.W.WindowActiveDesktopVisibleOnly\",\n              \"Tag\": \"mouse_node_w_\"\n            },\n            {\n              \"Name\": \"ContextMenu\",\n              \"Header\": \"M.ContextMenu\",\n              \"Tag\": \"mouse_node_w_\"\n            },\n            {\n              \"Name\": \"WindowHideFromView\",\n              \"Header\": \"M.W.WindowHideFromView\",\n              \"Tag\": \"mouse_node_w_\"\n            },\n            {\n              \"Name\": \"WindowClose\",\n              \"Header\": \"M.W.WindowClose\",\n              \"Tag\": \"mouse_node_w_\"\n            },\n            {\n              \"Name\": \"WindowShowForSelectedProcessOnly\",\n              \"Header\": \"M.W.WindowShowForSelectedProcessOnly\",\n              \"Tag\": \"mouse_node_w_\"\n            },\n            {\n              \"Name\": \"WindowShowForSelectedProcessInSelectedDesktop\",\n              \"Header\": \"M.W.WindowShowForSelectedProcessInSelectedDesktop\",\n              \"Tag\": \"mouse_node_w_\"\n            }\n          ]\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "WPF/ControlPanel/Resources/Langs.Designer.cs",
    "content": "﻿//------------------------------------------------------------------------------\n// <auto-generated>\n//     This code was generated by a tool.\n//\n//     Changes to this file may cause incorrect behavior and will be lost if\n//     the code is regenerated.\n// </auto-generated>\n//------------------------------------------------------------------------------\n\nnamespace ControlPanel.Resources {\n    using System;\n    \n    \n    /// <summary>\n    ///   A strongly-typed resource class, for looking up localized strings, etc.\n    /// </summary>\n    // This class was auto-generated by the StronglyTypedResourceBuilder\n    // class via a tool like ResGen or Visual Studio.\n    // To add or remove a member, edit your .ResX file then rerun ResGen\n    // with the /str option, or rebuild your VS project.\n    [global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Resources.Tools.StronglyTypedResourceBuilder\", \"17.0.0.0\")]\n    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]\n    internal class Langs {\n        \n        private static global::System.Resources.ResourceManager resourceMan;\n        \n        private static global::System.Globalization.CultureInfo resourceCulture;\n        \n        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute(\"Microsoft.Performance\", \"CA1811:AvoidUncalledPrivateCode\")]\n        internal Langs() {\n        }\n        \n        /// <summary>\n        ///   Returns the cached ResourceManager instance used by this class.\n        /// </summary>\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\n        internal static global::System.Resources.ResourceManager ResourceManager {\n            get {\n                if (object.ReferenceEquals(resourceMan, null)) {\n                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager(\"ControlPanel.Resources.Langs\", typeof(Langs).Assembly);\n                    resourceMan = temp;\n                }\n                return resourceMan;\n            }\n        }\n        \n        /// <summary>\n        ///   Overrides the current thread's CurrentUICulture property for all\n        ///   resource lookups using this strongly typed resource class.\n        /// </summary>\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\n        internal static global::System.Globalization.CultureInfo Culture {\n            get {\n                return resourceCulture;\n            }\n            set {\n                resourceCulture = value;\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Cancel.\n        /// </summary>\n        internal static string Dialogs_Cancel {\n            get {\n                return ResourceManager.GetString(\"Dialogs.Cancel\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to OK.\n        /// </summary>\n        internal static string Dialogs_OK {\n            get {\n                return ResourceManager.GetString(\"Dialogs.OK\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Filter.\n        /// </summary>\n        internal static string Generic_Filter {\n            get {\n                return ResourceManager.GetString(\"Generic.Filter\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Name.\n        /// </summary>\n        internal static string Generic_Name {\n            get {\n                return ResourceManager.GetString(\"Generic.Name\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Clear.\n        /// </summary>\n        internal static string logTab_Menu_Clear {\n            get {\n                return ResourceManager.GetString(\"logTab.Menu.Clear\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Debug.\n        /// </summary>\n        internal static string logTabDebug {\n            get {\n                return ResourceManager.GetString(\"logTabDebug\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Error.\n        /// </summary>\n        internal static string logTabError {\n            get {\n                return ResourceManager.GetString(\"logTabError\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Event.\n        /// </summary>\n        internal static string logTabEvent {\n            get {\n                return ResourceManager.GetString(\"logTabEvent\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Info.\n        /// </summary>\n        internal static string logTabInfo {\n            get {\n                return ResourceManager.GetString(\"logTabInfo\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Verbose.\n        /// </summary>\n        internal static string logTabVerbose {\n            get {\n                return ResourceManager.GetString(\"logTabVerbose\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Warning.\n        /// </summary>\n        internal static string logTabWarning {\n            get {\n                return ResourceManager.GetString(\"logTabWarning\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Close this window.\n        /// </summary>\n        internal static string Menus_Commons_Close {\n            get {\n                return ResourceManager.GetString(\"Menus.Commons.Close\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Restart.\n        /// </summary>\n        internal static string Menus_Commons_Restart {\n            get {\n                return ResourceManager.GetString(\"Menus.Commons.Restart\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Run As Administrator.\n        /// </summary>\n        internal static string Menus_Commons_RunAsAdmin {\n            get {\n                return ResourceManager.GetString(\"Menus.Commons.RunAsAdmin\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Shutdown Application.\n        /// </summary>\n        internal static string Menus_Commons_Shutdown {\n            get {\n                return ResourceManager.GetString(\"Menus.Commons.Shutdown\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Switch Theme.\n        /// </summary>\n        internal static string Menus_Commons_Theme_Change {\n            get {\n                return ResourceManager.GetString(\"Menus.Commons.Theme.Change\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Clear all logs.\n        /// </summary>\n        internal static string Menus_Logs_ClearAll {\n            get {\n                return ResourceManager.GetString(\"Menus.Logs.ClearAll\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Open Logs Folder....\n        /// </summary>\n        internal static string Menus_Logs_OpenLogsDir {\n            get {\n                return ResourceManager.GetString(\"Menus.Logs.OpenLogsDir\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Show Context Menu.\n        /// </summary>\n        internal static string Mouse_Action_ContextMenu {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.ContextMenu\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Show Only Selected Desktop in MainView.\n        /// </summary>\n        internal static string Mouse_Action_DesktopShowForSelectedDesktop {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.DesktopShowForSelectedDesktop\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Switch Desktop And Close View.\n        /// </summary>\n        internal static string Mouse_Action_DesktopVisibleAndCloseView {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.DesktopVisibleAndCloseView\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Switch Desktop Only.\n        /// </summary>\n        internal static string Mouse_Action_DesktopVisibleOnly {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.DesktopVisibleOnly\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Do Nothing.\n        /// </summary>\n        internal static string Mouse_Action_DoNothing {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.DoNothing\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Active Window, Switch Virtual Desktop And Close View.\n        /// </summary>\n        internal static string Mouse_Action_WindowActiveDesktopVisibleAndCloseView {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.WindowActiveDesktopVisibleAndCloseView\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Active Window, Switch Virtual Desktop Only.\n        /// </summary>\n        internal static string Mouse_Action_WindowActiveDesktopVisibleOnly {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.WindowActiveDesktopVisibleOnly\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Close Window.\n        /// </summary>\n        internal static string Mouse_Action_WindowClose {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.WindowClose\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Hide From View.\n        /// </summary>\n        internal static string Mouse_Action_WindowHideFromView {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.WindowHideFromView\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Show Windows Only From Selected App in Selected Desktop.\n        /// </summary>\n        internal static string Mouse_Action_WindowShowForSelectedProcessInSelectedDesktop {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.WindowShowForSelectedProcessInSelectedDesktop\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Show Windows Only From Selected App.\n        /// </summary>\n        internal static string Mouse_Action_WindowShowForSelectedProcessOnly {\n            get {\n                return ResourceManager.GetString(\"Mouse.Action.WindowShowForSelectedProcessOnly\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to About.\n        /// </summary>\n        internal static string NavBar_About {\n            get {\n                return ResourceManager.GetString(\"NavBar.About\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Control.\n        /// </summary>\n        internal static string NavBar_Control {\n            get {\n                return ResourceManager.GetString(\"NavBar.Control\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to General.\n        /// </summary>\n        internal static string NavBar_General {\n            get {\n                return ResourceManager.GetString(\"NavBar.General\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Help.\n        /// </summary>\n        internal static string NavBar_Help {\n            get {\n                return ResourceManager.GetString(\"NavBar.Help\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Logs.\n        /// </summary>\n        internal static string NavBar_Logs {\n            get {\n                return ResourceManager.GetString(\"NavBar.Logs\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Plugins.\n        /// </summary>\n        internal static string NavBar_Plugins {\n            get {\n                return ResourceManager.GetString(\"NavBar.Plugins\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Rules.\n        /// </summary>\n        internal static string NavBar_Rules {\n            get {\n                return ResourceManager.GetString(\"NavBar.Rules\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Settings.\n        /// </summary>\n        internal static string NavBar_Settings {\n            get {\n                return ResourceManager.GetString(\"NavBar.Settings\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Theme.\n        /// </summary>\n        internal static string NavBar_Theme {\n            get {\n                return ResourceManager.GetString(\"NavBar.Theme\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to UI.\n        /// </summary>\n        internal static string NavBar_UI {\n            get {\n                return ResourceManager.GetString(\"NavBar.UI\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Note: If and only when the number of virtual desktops is the square of the natural number [1,n], the arrangement can be changed; \n        ///if the conditions are not satisfied, the program will automatically reset to the first arrangement..\n        /// </summary>\n        internal static string Note_DesktopArrangement {\n            get {\n                return ResourceManager.GetString(\"Note.DesktopArrangement\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Note: more details such as delay of start can be set in.\n        /// </summary>\n        internal static string Note_General_Label_TaskScheduler {\n            get {\n                return ResourceManager.GetString(\"Note.General.Label.TaskScheduler\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Note: KeyBindings, MouseActions, LogConfigs and StorageConfigs are shared by all profiles(regardless of profiles). \n        ///some settings may need restart program to take effect..\n        /// </summary>\n        internal static string Note_Settings_Profiles {\n            get {\n                return ResourceManager.GetString(\"Note.Settings.Profiles\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Note: change config folder need restart program. this operation only change location, no files will be copied or moved to avoid overwrite files unexpectedly. \n        ///if you want reuse current configs, you may manually copy &quot;Related Content&quot; to the folder you choosed, then restart program.\n        ///Related Content: Settings.json, Profiles\\*.*.\n        /// </summary>\n        internal static string Note_Settings_Storage {\n            get {\n                return ResourceManager.GetString(\"Note.Settings.Storage\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Clear and Save.\n        /// </summary>\n        internal static string Page_Control_KB_ClearSave {\n            get {\n                return ResourceManager.GetString(\"Page.Control.KB.ClearSave\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Alternate.\n        /// </summary>\n        internal static string Page_Control_KB_Extra {\n            get {\n                return ResourceManager.GetString(\"Page.Control.KB.Extra\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Register and Save.\n        /// </summary>\n        internal static string Page_Control_KB_RegSave {\n            get {\n                return ResourceManager.GetString(\"Page.Control.KB.RegSave\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Keyboard.\n        /// </summary>\n        internal static string Page_Control_Keyboard {\n            get {\n                return ResourceManager.GetString(\"Page.Control.Keyboard\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Mouse.\n        /// </summary>\n        internal static string Page_Control_Mouse {\n            get {\n                return ResourceManager.GetString(\"Page.Control.Mouse\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to When mouse hover on Taskbar, Use wheel switch virtual desktop..\n        /// </summary>\n        internal static string Page_Control_Mouse_UseWheelSwitchDesktopWhenOnTaskbar {\n            get {\n                return ResourceManager.GetString(\"Page.Control.Mouse.UseWheelSwitchDesktopWhenOnTaskbar\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to SHIFT+Scroll Up =&gt; Go Up.\n        /// </summary>\n        internal static string Page_Control_Mouse_Wheel_Down {\n            get {\n                return ResourceManager.GetString(\"Page.Control.Mouse.Wheel.Down\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to SHIFT+Scroll Down =&gt; Go Down.\n        /// </summary>\n        internal static string Page_Control_Mouse_Wheel_SDown {\n            get {\n                return ResourceManager.GetString(\"Page.Control.Mouse.Wheel.SDown\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Scroll Down =&gt; Go Right.\n        /// </summary>\n        internal static string Page_Control_Mouse_Wheel_SUp {\n            get {\n                return ResourceManager.GetString(\"Page.Control.Mouse.Wheel.SUp\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Scroll Up =&gt; Go Left.\n        /// </summary>\n        internal static string Page_Control_Mouse_Wheel_Up {\n            get {\n                return ResourceManager.GetString(\"Page.Control.Mouse.Wheel.Up\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 🖇️.\n        /// </summary>\n        internal static string Page_Control_MouseAction_Behavior {\n            get {\n                return ResourceManager.GetString(\"Page.Control.MouseAction.Behavior\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Bind.\n        /// </summary>\n        internal static string Page_Control_MouseAction_Bind {\n            get {\n                return ResourceManager.GetString(\"Page.Control.MouseAction.Bind\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Clear.\n        /// </summary>\n        internal static string Page_Control_MouseAction_Clear {\n            get {\n                return ResourceManager.GetString(\"Page.Control.MouseAction.Clear\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to First select the MouseAction from the left side of the 🖇️ icon, then choose a behavior from the right side of the 🖇️ icon, and finally bind..\n        /// </summary>\n        internal static string Page_Control_MouseAction_DesktopBindings {\n            get {\n                return ResourceManager.GetString(\"Page.Control.MouseAction.DesktopBindings\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Expand for details..\n        /// </summary>\n        internal static string Page_Control_MouseAction_ExpanderHeader {\n            get {\n                return ResourceManager.GetString(\"Page.Control.MouseAction.ExpanderHeader\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Click on a virtual desktop in the MainView.\n        /// </summary>\n        internal static string Page_Control_MouseAction_OnDesktop {\n            get {\n                return ResourceManager.GetString(\"Page.Control.MouseAction.OnDesktop\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Click on a window thumbnail in the MainView.\n        /// </summary>\n        internal static string Page_Control_MouseAction_OnThumb {\n            get {\n                return ResourceManager.GetString(\"Page.Control.MouseAction.OnThumb\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Save.\n        /// </summary>\n        internal static string Page_Control_MouseAction_Save {\n            get {\n                return ResourceManager.GetString(\"Page.Control.MouseAction.Save\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to First select the MouseAction from the left side of the 🖇️ icon, then choose a behavior from the right side of the 🖇️ icon, and finally bind..\n        /// </summary>\n        internal static string Page_Control_MouseAction_WindowBindings {\n            get {\n                return ResourceManager.GetString(\"Page.Control.MouseAction.WindowBindings\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Left.\n        /// </summary>\n        internal static string Page_Control_MouseButtons_Left {\n            get {\n                return ResourceManager.GetString(\"Page.Control.MouseButtons.Left\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Middle.\n        /// </summary>\n        internal static string Page_Control_MouseButtons_Middle {\n            get {\n                return ResourceManager.GetString(\"Page.Control.MouseButtons.Middle\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Right.\n        /// </summary>\n        internal static string Page_Control_MouseButtons_Right {\n            get {\n                return ResourceManager.GetString(\"Page.Control.MouseButtons.Right\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Basics.\n        /// </summary>\n        internal static string Page_General_Basics {\n            get {\n                return ResourceManager.GetString(\"Page.General.Basics\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Cluster.\n        /// </summary>\n        internal static string Page_General_Cluster {\n            get {\n                return ResourceManager.GetString(\"Page.General.Cluster\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to When the MainView shown, [Double LShift] to open WindowFilter..\n        /// </summary>\n        internal static string Page_General_EnableWindowFilter {\n            get {\n                return ResourceManager.GetString(\"Page.General.EnableWindowFilter\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to When use hotkey rise the MainView, Close it if the MainView already shown..\n        /// </summary>\n        internal static string Page_General_HideMainViewIfItsShown {\n            get {\n                return ResourceManager.GetString(\"Page.General.HideMainViewIfItsShown\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Hide MainView when program start..\n        /// </summary>\n        internal static string Page_General_HideOnStart {\n            get {\n                return ResourceManager.GetString(\"Page.General.HideOnStart\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Enable circulation..\n        /// </summary>\n        internal static string Page_General_Nav_H {\n            get {\n                return ResourceManager.GetString(\"Page.General.Nav.H\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Right end of row joins to left end of:.\n        /// </summary>\n        internal static string Page_General_Nav_HType {\n            get {\n                return ResourceManager.GetString(\"Page.General.Nav.HType\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Next row.\n        /// </summary>\n        internal static string Page_General_Nav_HType_0 {\n            get {\n                return ResourceManager.GetString(\"Page.General.Nav.HType.0\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Same row.\n        /// </summary>\n        internal static string Page_General_Nav_HType_1 {\n            get {\n                return ResourceManager.GetString(\"Page.General.Nav.HType.1\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Circulate vertically. (same col only).\n        /// </summary>\n        internal static string Page_General_Nav_V {\n            get {\n                return ResourceManager.GetString(\"Page.General.Nav.V\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Navigation.\n        /// </summary>\n        internal static string Page_General_Navigation {\n            get {\n                return ResourceManager.GetString(\"Page.General.Navigation\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Show notification when Current virtual desktop changed..\n        /// </summary>\n        internal static string Page_General_NotificationOnVdChanged {\n            get {\n                return ResourceManager.GetString(\"Page.General.NotificationOnVdChanged\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Launch program at system startup..\n        /// </summary>\n        internal static string Page_General_RunOnStartup {\n            get {\n                return ResourceManager.GetString(\"Page.General.RunOnStartup\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Show virtual desktop index on Tray Icon..\n        /// </summary>\n        internal static string Page_General_ShowVDIndexOnTrayIcon {\n            get {\n                return ResourceManager.GetString(\"Page.General.ShowVDIndexOnTrayIcon\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Default.\n        /// </summary>\n        internal static string Page_General_StyleOfVDIndexOnTrayIcon_0 {\n            get {\n                return ResourceManager.GetString(\"Page.General.StyleOfVDIndexOnTrayIcon.0\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to High Contrast 1.\n        /// </summary>\n        internal static string Page_General_StyleOfVDIndexOnTrayIcon_1 {\n            get {\n                return ResourceManager.GetString(\"Page.General.StyleOfVDIndexOnTrayIcon.1\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to High Contrast 2.\n        /// </summary>\n        internal static string Page_General_StyleOfVDIndexOnTrayIcon_2 {\n            get {\n                return ResourceManager.GetString(\"Page.General.StyleOfVDIndexOnTrayIcon.2\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Task Scheduler.\n        /// </summary>\n        internal static string Page_General_TaskScheduler {\n            get {\n                return ResourceManager.GetString(\"Page.General.TaskScheduler\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Show Logs In GUI.\n        /// </summary>\n        internal static string Page_Logs_IsPrintLogs {\n            get {\n                return ResourceManager.GetString(\"Page.Logs.IsPrintLogs\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Author.\n        /// </summary>\n        internal static string Page_Plugins_Author {\n            get {\n                return ResourceManager.GetString(\"Page.Plugins.Author\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Close.\n        /// </summary>\n        internal static string Page_Plugins_Close {\n            get {\n                return ResourceManager.GetString(\"Page.Plugins.Close\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Email.\n        /// </summary>\n        internal static string Page_Plugins_Email {\n            get {\n                return ResourceManager.GetString(\"Page.Plugins.Email\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Name.\n        /// </summary>\n        internal static string Page_Plugins_Name {\n            get {\n                return ResourceManager.GetString(\"Page.Plugins.Name\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Operations.\n        /// </summary>\n        internal static string Page_Plugins_Operations {\n            get {\n                return ResourceManager.GetString(\"Page.Plugins.Operations\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Restart.\n        /// </summary>\n        internal static string Page_Plugins_Restart {\n            get {\n                return ResourceManager.GetString(\"Page.Plugins.Restart\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Settings.\n        /// </summary>\n        internal static string Page_Plugins_Settings {\n            get {\n                return ResourceManager.GetString(\"Page.Plugins.Settings\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Version.\n        /// </summary>\n        internal static string Page_Plugins_Version {\n            get {\n                return ResourceManager.GetString(\"Page.Plugins.Version\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to New....\n        /// </summary>\n        internal static string Page_Rules_Add {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Add\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Clone.\n        /// </summary>\n        internal static string Page_Rules_Clone {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Clone\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Created.\n        /// </summary>\n        internal static string Page_Rules_Created {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Created\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Remove(Del).\n        /// </summary>\n        internal static string Page_Rules_Delete {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Delete\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Edit(E)....\n        /// </summary>\n        internal static string Page_Rules_Edit {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Edit\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Edit Rule Definition.\n        /// </summary>\n        internal static string Page_Rules_EditRule {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.EditRule\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to New Rule Definition.\n        /// </summary>\n        internal static string Page_Rules_NewRule {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.NewRule\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Basics.\n        /// </summary>\n        internal static string Page_Rules_Rule_Basic {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.Basic\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Cancel.\n        /// </summary>\n        internal static string Page_Rules_Rule_CloseDefBox {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.CloseDefBox\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Command Line.\n        /// </summary>\n        internal static string Page_Rules_Rule_CommandLine {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.CommandLine\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Created.\n        /// </summary>\n        internal static string Page_Rules_Rule_Created {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.Created\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Enabled.\n        /// </summary>\n        internal static string Page_Rules_Rule_Enabled {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.Enabled\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Follow Window.\n        /// </summary>\n        internal static string Page_Rules_Rule_FollowWindow {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.FollowWindow\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Hide From View.\n        /// </summary>\n        internal static string Page_Rules_Rule_HideFromView {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.HideFromView\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Move To Desktop.\n        /// </summary>\n        internal static string Page_Rules_Rule_MoveToDesktop {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.MoveToDesktop\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Move To Screen.\n        /// </summary>\n        internal static string Page_Rules_Rule_MoveToScreen {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.MoveToScreen\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to ends with.\n        /// </summary>\n        internal static string Page_Rules_Rule_Op_esw {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.Op.esw\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to regex.\n        /// </summary>\n        internal static string Page_Rules_Rule_Op_rim {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.Op.rim\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to contains.\n        /// </summary>\n        internal static string Page_Rules_Rule_Op_sc {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.Op.sc\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to starts with.\n        /// </summary>\n        internal static string Page_Rules_Rule_Op_ssw {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.Op.ssw\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Pin Application of Window.\n        /// </summary>\n        internal static string Page_Rules_Rule_PinApp {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.PinApp\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Pin Window.\n        /// </summary>\n        internal static string Page_Rules_Rule_PinWindow {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.PinWindow\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Process Name.\n        /// </summary>\n        internal static string Page_Rules_Rule_ProcessName {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.ProcessName\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Process Path.\n        /// </summary>\n        internal static string Page_Rules_Rule_ProcessPath {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.ProcessPath\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Save and Close.\n        /// </summary>\n        internal static string Page_Rules_Rule_Save {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.Save\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Tag(Group).\n        /// </summary>\n        internal static string Page_Rules_Rule_Tag {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.Tag\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Window Title.\n        /// </summary>\n        internal static string Page_Rules_Rule_Title {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.Title\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Updated.\n        /// </summary>\n        internal static string Page_Rules_Rule_Updated {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.Updated\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Window Actions.\n        /// </summary>\n        internal static string Page_Rules_Rule_WindowActions {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.WindowActions\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Common Window Rules.\n        /// </summary>\n        internal static string Page_Rules_Rule_WindowRules {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.WindowRules\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Window In Screen.\n        /// </summary>\n        internal static string Page_Rules_Rule_WinInScreen {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.WinInScreen\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Window Class.\n        /// </summary>\n        internal static string Page_Rules_Rule_WndClass {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Rule.WndClass\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Tag(Group).\n        /// </summary>\n        internal static string Page_Rules_Tag {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Tag\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Updated.\n        /// </summary>\n        internal static string Page_Rules_Updated {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Updated\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Weight.\n        /// </summary>\n        internal static string Page_Rules_Weight {\n            get {\n                return ResourceManager.GetString(\"Page.Rules.Weight\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Language.\n        /// </summary>\n        internal static string Page_Settings_Language {\n            get {\n                return ResourceManager.GetString(\"Page.Settings.Language\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Delete.\n        /// </summary>\n        internal static string Page_Settings_Menus_Delete {\n            get {\n                return ResourceManager.GetString(\"Page.Settings.Menus.Delete\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Duplicate.\n        /// </summary>\n        internal static string Page_Settings_Menus_Duplicate {\n            get {\n                return ResourceManager.GetString(\"Page.Settings.Menus.Duplicate\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Rename.\n        /// </summary>\n        internal static string Page_Settings_Menus_Rename {\n            get {\n                return ResourceManager.GetString(\"Page.Settings.Menus.Rename\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Profiles.\n        /// </summary>\n        internal static string Page_Settings_ProfileManager {\n            get {\n                return ResourceManager.GetString(\"Page.Settings.ProfileManager\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Storage.\n        /// </summary>\n        internal static string Page_Settings_Storage {\n            get {\n                return ResourceManager.GetString(\"Page.Settings.Storage\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Change....\n        /// </summary>\n        internal static string Page_Settings_Storage_ChangeConfigPath {\n            get {\n                return ResourceManager.GetString(\"Page.Settings.Storage.ChangeConfigPath\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Parent Folder of Configs.\n        /// </summary>\n        internal static string Page_Settings_Storage_ConfigRootPath {\n            get {\n                return ResourceManager.GetString(\"Page.Settings.Storage.ConfigRootPath\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Theme.\n        /// </summary>\n        internal static string Page_Settings_Theme {\n            get {\n                return ResourceManager.GetString(\"Page.Settings.Theme\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Dark.\n        /// </summary>\n        internal static string Page_Settings_Theme_Dark {\n            get {\n                return ResourceManager.GetString(\"Page.Settings.Theme.Dark\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Light.\n        /// </summary>\n        internal static string Page_Settings_Theme_Light {\n            get {\n                return ResourceManager.GetString(\"Page.Settings.Theme.Light\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to System Settings.\n        /// </summary>\n        internal static string Page_Settings_Theme_Sys {\n            get {\n                return ResourceManager.GetString(\"Page.Settings.Theme.Sys\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to TopLeft to BottomRight, Horizontal.\n        /// </summary>\n        internal static string Page_UI_Label_m0 {\n            get {\n                return ResourceManager.GetString(\"Page.UI.Label.m0\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to TopRight to BottomLeft, Horizontal.\n        /// </summary>\n        internal static string Page_UI_Label_m1 {\n            get {\n                return ResourceManager.GetString(\"Page.UI.Label.m1\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to BottomLeft to TopRight, Horizontal.\n        /// </summary>\n        internal static string Page_UI_Label_m2 {\n            get {\n                return ResourceManager.GetString(\"Page.UI.Label.m2\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to BottomRight to TopLeft, Horizontal.\n        /// </summary>\n        internal static string Page_UI_Label_m3 {\n            get {\n                return ResourceManager.GetString(\"Page.UI.Label.m3\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to TopLeft to BottomRight, Vertical.\n        /// </summary>\n        internal static string Page_UI_Label_m4 {\n            get {\n                return ResourceManager.GetString(\"Page.UI.Label.m4\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to TopRight to BottomLeft, Vertical.\n        /// </summary>\n        internal static string Page_UI_Label_m5 {\n            get {\n                return ResourceManager.GetString(\"Page.UI.Label.m5\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to BottomLeft to TopRight, Vertical.\n        /// </summary>\n        internal static string Page_UI_Label_m6 {\n            get {\n                return ResourceManager.GetString(\"Page.UI.Label.m6\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to BottomRight to TopLeft, Vertical.\n        /// </summary>\n        internal static string Page_UI_Label_m7 {\n            get {\n                return ResourceManager.GetString(\"Page.UI.Label.m7\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Show Virtual Desktop Index.\n        /// </summary>\n        internal static string Page_UI_ShowVdIndex {\n            get {\n                return ResourceManager.GetString(\"Page.UI.ShowVdIndex\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 1-based.\n        /// </summary>\n        internal static string Page_UI_ShowVdIndex_OneBased {\n            get {\n                return ResourceManager.GetString(\"Page.UI.ShowVdIndex.OneBased\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 0-based.\n        /// </summary>\n        internal static string Page_UI_ShowVdIndex_ZeroBased {\n            get {\n                return ResourceManager.GetString(\"Page.UI.ShowVdIndex.ZeroBased\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Show Virtual Desktop Name.\n        /// </summary>\n        internal static string Page_UI_ShowVdName {\n            get {\n                return ResourceManager.GetString(\"Page.UI.ShowVdName\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Virtual Desktop Arrangement.\n        /// </summary>\n        internal static string Page_UI_VdArrangement {\n            get {\n                return ResourceManager.GetString(\"Page.UI.VdArrangement\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Virtual Desktop View.\n        /// </summary>\n        internal static string Page_UI_VdView {\n            get {\n                return ResourceManager.GetString(\"Page.UI.VdView\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Field is required..\n        /// </summary>\n        internal static string Validation_Error_Required {\n            get {\n                return ResourceManager.GetString(\"Validation.Error.Required\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Rule Definition.\n        /// </summary>\n        internal static string Window_RuleDefinition {\n            get {\n                return ResourceManager.GetString(\"Window.RuleDefinition\", resourceCulture);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "WPF/ControlPanel/Resources/Langs.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"logTab.Menu.Clear\" xml:space=\"preserve\">\n    <value>Clear</value>\n  </data>\n  <data name=\"logTabDebug\" xml:space=\"preserve\">\n    <value>Debug</value>\n  </data>\n  <data name=\"logTabError\" xml:space=\"preserve\">\n    <value>Error</value>\n  </data>\n  <data name=\"NavBar.Rules\" xml:space=\"preserve\">\n    <value>Rules</value>\n  </data>\n  <data name=\"logTabInfo\" xml:space=\"preserve\">\n    <value>Info</value>\n  </data>\n  <data name=\"logTabWarning\" xml:space=\"preserve\">\n    <value>Warning</value>\n  </data>\n  <data name=\"NavBar.General\" xml:space=\"preserve\">\n    <value>General</value>\n  </data>\n  <data name=\"NavBar.Logs\" xml:space=\"preserve\">\n    <value>Logs</value>\n  </data>\n  <data name=\"NavBar.UI\" xml:space=\"preserve\">\n    <value>UI</value>\n  </data>\n  <data name=\"NavBar.Theme\" xml:space=\"preserve\">\n    <value>Theme</value>\n  </data>\n  <data name=\"NavBar.Settings\" xml:space=\"preserve\">\n    <value>Settings</value>\n  </data>\n  <data name=\"NavBar.Plugins\" xml:space=\"preserve\">\n    <value>Plugins</value>\n  </data>\n  <data name=\"NavBar.Help\" xml:space=\"preserve\">\n    <value>Help</value>\n  </data>\n  <data name=\"Page.Settings.Language\" xml:space=\"preserve\">\n    <value>Language</value>\n  </data>\n  <data name=\"logTabVerbose\" xml:space=\"preserve\">\n    <value>Verbose</value>\n  </data>\n  <data name=\"logTabEvent\" xml:space=\"preserve\">\n    <value>Event</value>\n  </data>\n  <data name=\"Page.Settings.Theme.Sys\" xml:space=\"preserve\">\n    <value>System Settings</value>\n  </data>\n  <data name=\"Page.Settings.Theme\" xml:space=\"preserve\">\n    <value>Theme</value>\n  </data>\n  <data name=\"Page.Settings.Theme.Light\" xml:space=\"preserve\">\n    <value>Light</value>\n  </data>\n  <data name=\"Page.Settings.Theme.Dark\" xml:space=\"preserve\">\n    <value>Dark</value>\n  </data>\n  <data name=\"Menus.Commons.Theme.Change\" xml:space=\"preserve\">\n    <value>Switch Theme</value>\n  </data>\n  <data name=\"Page.Logs.IsPrintLogs\" xml:space=\"preserve\">\n    <value>Show Logs In GUI</value>\n  </data>\n  <data name=\"Menus.Logs.OpenLogsDir\" xml:space=\"preserve\">\n    <value>Open Logs Folder...</value>\n  </data>\n  <data name=\"Menus.Logs.ClearAll\" xml:space=\"preserve\">\n    <value>Clear all logs</value>\n  </data>\n  <data name=\"Menus.Commons.Close\" xml:space=\"preserve\">\n    <value>Close this window</value>\n  </data>\n  <data name=\"Menus.Commons.Restart\" xml:space=\"preserve\">\n    <value>Restart</value>\n  </data>\n  <data name=\"Menus.Commons.Shutdown\" xml:space=\"preserve\">\n    <value>Shutdown Application</value>\n  </data>\n  <data name=\"Page.Plugins.Name\" xml:space=\"preserve\">\n    <value>Name</value>\n  </data>\n  <data name=\"Page.Plugins.Version\" xml:space=\"preserve\">\n    <value>Version</value>\n  </data>\n  <data name=\"Page.Plugins.Author\" xml:space=\"preserve\">\n    <value>Author</value>\n  </data>\n  <data name=\"Page.Plugins.Email\" xml:space=\"preserve\">\n    <value>Email</value>\n  </data>\n  <data name=\"Page.Plugins.Operations\" xml:space=\"preserve\">\n    <value>Operations</value>\n  </data>\n  <data name=\"Page.Plugins.Settings\" xml:space=\"preserve\">\n    <value>Settings</value>\n  </data>\n  <data name=\"Page.Plugins.Restart\" xml:space=\"preserve\">\n    <value>Restart</value>\n  </data>\n  <data name=\"Page.Plugins.Close\" xml:space=\"preserve\">\n    <value>Close</value>\n  </data>\n  <data name=\"Page.Rules.Updated\" xml:space=\"preserve\">\n    <value>Updated</value>\n  </data>\n  <data name=\"Page.Rules.Created\" xml:space=\"preserve\">\n    <value>Created</value>\n  </data>\n  <data name=\"Page.Rules.Add\" xml:space=\"preserve\">\n    <value>New...</value>\n  </data>\n  <data name=\"Page.Rules.Edit\" xml:space=\"preserve\">\n    <value>Edit(E)...</value>\n  </data>\n  <data name=\"Page.Rules.Clone\" xml:space=\"preserve\">\n    <value>Clone</value>\n  </data>\n  <data name=\"Page.Rules.Delete\" xml:space=\"preserve\">\n    <value>Remove(Del)</value>\n  </data>\n  <data name=\"Page.Rules.NewRule\" xml:space=\"preserve\">\n    <value>New Rule Definition</value>\n  </data>\n  <data name=\"Page.Rules.EditRule\" xml:space=\"preserve\">\n    <value>Edit Rule Definition</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Enabled\" xml:space=\"preserve\">\n    <value>Enabled</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Basic\" xml:space=\"preserve\">\n    <value>Basics</value>\n  </data>\n  <data name=\"Generic.Name\" xml:space=\"preserve\">\n    <value>Name</value>\n  </data>\n  <data name=\"Validation.Error.Required\" xml:space=\"preserve\">\n    <value>Field is required.</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Created\" xml:space=\"preserve\">\n    <value>Created</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Updated\" xml:space=\"preserve\">\n    <value>Updated</value>\n  </data>\n  <data name=\"Page.Rules.Rule.WindowRules\" xml:space=\"preserve\">\n    <value>Common Window Rules</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Title\" xml:space=\"preserve\">\n    <value>Window Title</value>\n  </data>\n  <data name=\"Page.Rules.Rule.ProcessName\" xml:space=\"preserve\">\n    <value>Process Name</value>\n  </data>\n  <data name=\"Page.Rules.Rule.ProcessPath\" xml:space=\"preserve\">\n    <value>Process Path</value>\n  </data>\n  <data name=\"Page.Rules.Rule.WndClass\" xml:space=\"preserve\">\n    <value>Window Class</value>\n  </data>\n  <data name=\"Page.Rules.Rule.WinInScreen\" xml:space=\"preserve\">\n    <value>Window In Screen</value>\n  </data>\n  <data name=\"Page.Rules.Rule.CloseDefBox\" xml:space=\"preserve\">\n    <value>Cancel</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Save\" xml:space=\"preserve\">\n    <value>Save and Close</value>\n  </data>\n  <data name=\"Page.Rules.Rule.CommandLine\" xml:space=\"preserve\">\n    <value>Command Line</value>\n  </data>\n  <data name=\"Page.Rules.Rule.WindowActions\" xml:space=\"preserve\">\n    <value>Window Actions</value>\n  </data>\n  <data name=\"Page.Rules.Rule.MoveToDesktop\" xml:space=\"preserve\">\n    <value>Move To Desktop</value>\n  </data>\n  <data name=\"Page.Rules.Rule.FollowWindow\" xml:space=\"preserve\">\n    <value>Follow Window</value>\n  </data>\n  <data name=\"Page.Rules.Rule.PinWindow\" xml:space=\"preserve\">\n    <value>Pin Window</value>\n  </data>\n  <data name=\"Page.Rules.Rule.PinApp\" xml:space=\"preserve\">\n    <value>Pin Application of Window</value>\n  </data>\n  <data name=\"Page.Rules.Rule.HideFromView\" xml:space=\"preserve\">\n    <value>Hide From View</value>\n  </data>\n  <data name=\"Page.Rules.Rule.MoveToScreen\" xml:space=\"preserve\">\n    <value>Move To Screen</value>\n  </data>\n  <data name=\"Page.UI.VdArrangement\" xml:space=\"preserve\">\n    <value>Virtual Desktop Arrangement</value>\n  </data>\n  <data name=\"Page.UI.VdView\" xml:space=\"preserve\">\n    <value>Virtual Desktop View</value>\n  </data>\n  <data name=\"Page.UI.ShowVdName\" xml:space=\"preserve\">\n    <value>Show Virtual Desktop Name</value>\n  </data>\n  <data name=\"Page.UI.ShowVdIndex\" xml:space=\"preserve\">\n    <value>Show Virtual Desktop Index</value>\n  </data>\n  <data name=\"Page.UI.ShowVdIndex.ZeroBased\" xml:space=\"preserve\">\n    <value>0-based</value>\n  </data>\n  <data name=\"Page.UI.ShowVdIndex.OneBased\" xml:space=\"preserve\">\n    <value>1-based</value>\n  </data>\n  <data name=\"Note.DesktopArrangement\" xml:space=\"preserve\">\n    <value>Note: If and only when the number of virtual desktops is the square of the natural number [1,n], the arrangement can be changed; \nif the conditions are not satisfied, the program will automatically reset to the first arrangement.</value>\n  </data>\n  <data name=\"Page.UI.Label.m0\" xml:space=\"preserve\">\n    <value>TopLeft to BottomRight, Horizontal</value>\n  </data>\n  <data name=\"Page.UI.Label.m1\" xml:space=\"preserve\">\n    <value>TopRight to BottomLeft, Horizontal</value>\n  </data>\n  <data name=\"Page.UI.Label.m2\" xml:space=\"preserve\">\n    <value>BottomLeft to TopRight, Horizontal</value>\n  </data>\n  <data name=\"Page.UI.Label.m3\" xml:space=\"preserve\">\n    <value>BottomRight to TopLeft, Horizontal</value>\n  </data>\n  <data name=\"Page.UI.Label.m4\" xml:space=\"preserve\">\n    <value>TopLeft to BottomRight, Vertical</value>\n  </data>\n  <data name=\"Page.UI.Label.m5\" xml:space=\"preserve\">\n    <value>TopRight to BottomLeft, Vertical</value>\n  </data>\n  <data name=\"Page.UI.Label.m6\" xml:space=\"preserve\">\n    <value>BottomLeft to TopRight, Vertical</value>\n  </data>\n  <data name=\"Page.UI.Label.m7\" xml:space=\"preserve\">\n    <value>BottomRight to TopLeft, Vertical</value>\n  </data>\n  <data name=\"NavBar.Control\" xml:space=\"preserve\">\n    <value>Control</value>\n  </data>\n  <data name=\"Page.Control.Keyboard\" xml:space=\"preserve\">\n    <value>Keyboard</value>\n  </data>\n  <data name=\"Page.Control.Mouse\" xml:space=\"preserve\">\n    <value>Mouse</value>\n  </data>\n  <data name=\"Page.Control.KB.RegSave\" xml:space=\"preserve\">\n    <value>Register and Save</value>\n  </data>\n  <data name=\"Page.Control.KB.Extra\" xml:space=\"preserve\">\n    <value>Alternate</value>\n  </data>\n  <data name=\"Page.Control.KB.ClearSave\" xml:space=\"preserve\">\n    <value>Clear and Save</value>\n  </data>\n  <data name=\"Page.Rules.Tag\" xml:space=\"preserve\">\n    <value>Tag(Group)</value>\n  </data>\n  <data name=\"Generic.Filter\" xml:space=\"preserve\">\n    <value>Filter</value>\n  </data>\n  <data name=\"Page.Control.MouseAction.Save\" xml:space=\"preserve\">\n    <value>Save</value>\n  </data>\n  <data name=\"Page.Control.MouseAction.Clear\" xml:space=\"preserve\">\n    <value>Clear</value>\n  </data>\n  <data name=\"Page.Control.MouseButtons.Left\" xml:space=\"preserve\">\n    <value>Left</value>\n  </data>\n  <data name=\"Page.Control.MouseButtons.Middle\" xml:space=\"preserve\">\n    <value>Middle</value>\n  </data>\n  <data name=\"Page.Control.MouseButtons.Right\" xml:space=\"preserve\">\n    <value>Right</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Op.=\" xml:space=\"preserve\">\n    <value>is</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Op.ssw\" xml:space=\"preserve\">\n    <value>starts with</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Op.esw\" xml:space=\"preserve\">\n    <value>ends with</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Op.sc\" xml:space=\"preserve\">\n    <value>contains</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Op.rim\" xml:space=\"preserve\">\n    <value>regex</value>\n  </data>\n  <data name=\"Page.Control.MouseAction.OnDesktop\" xml:space=\"preserve\">\n    <value>Click on a virtual desktop in the MainView</value>\n  </data>\n  <data name=\"Page.Control.MouseAction.OnThumb\" xml:space=\"preserve\">\n    <value>Click on a window thumbnail in the MainView</value>\n  </data>\n  <data name=\"Page.Control.MouseAction.Behavior\" xml:space=\"preserve\">\n    <value>🖇️</value>\n  </data>\n  <data name=\"Mouse.Action.WindowHideFromView\" xml:space=\"preserve\">\n    <value>Hide From View</value>\n  </data>\n  <data name=\"Mouse.Action.DoNothing\" xml:space=\"preserve\">\n    <value>Do Nothing</value>\n  </data>\n  <data name=\"Mouse.Action.DesktopVisibleAndCloseView\" xml:space=\"preserve\">\n    <value>Switch Desktop And Close View</value>\n  </data>\n  <data name=\"Mouse.Action.DesktopVisibleOnly\" xml:space=\"preserve\">\n    <value>Switch Desktop Only</value>\n  </data>\n  <data name=\"Mouse.Action.ContextMenu\" xml:space=\"preserve\">\n    <value>Show Context Menu</value>\n  </data>\n  <data name=\"Mouse.Action.WindowActiveDesktopVisibleAndCloseView\" xml:space=\"preserve\">\n    <value>Active Window, Switch Virtual Desktop And Close View</value>\n  </data>\n  <data name=\"Mouse.Action.WindowActiveDesktopVisibleOnly\" xml:space=\"preserve\">\n    <value>Active Window, Switch Virtual Desktop Only</value>\n  </data>\n  <data name=\"Mouse.Action.WindowClose\" xml:space=\"preserve\">\n    <value>Close Window</value>\n  </data>\n  <data name=\"Mouse.Action.WindowShowForSelectedProcessOnly\" xml:space=\"preserve\">\n    <value>Show Windows Only From Selected App</value>\n  </data>\n  <data name=\"Mouse.Action.WindowShowForSelectedProcessInSelectedDesktop\" xml:space=\"preserve\">\n    <value>Show Windows Only From Selected App in Selected Desktop</value>\n  </data>\n  <data name=\"Mouse.Action.DesktopShowForSelectedDesktop\" xml:space=\"preserve\">\n    <value>Show Only Selected Desktop in MainView</value>\n  </data>\n  <data name=\"Page.Control.Mouse.UseWheelSwitchDesktopWhenOnTaskbar\" xml:space=\"preserve\">\n    <value>When mouse hover on Taskbar, Use wheel switch virtual desktop.</value>\n  </data>\n  <data name=\"Page.Control.Mouse.Wheel.Up\" xml:space=\"preserve\">\n    <value>Scroll Up =&gt; Go Left</value>\n  </data>\n  <data name=\"Page.Control.Mouse.Wheel.SUp\" xml:space=\"preserve\">\n    <value>Scroll Down =&gt; Go Right</value>\n  </data>\n  <data name=\"Page.Control.Mouse.Wheel.Down\" xml:space=\"preserve\">\n    <value>SHIFT+Scroll Up =&gt; Go Up</value>\n  </data>\n  <data name=\"Page.Control.Mouse.Wheel.SDown\" xml:space=\"preserve\">\n    <value>SHIFT+Scroll Down =&gt; Go Down</value>\n  </data>\n  <data name=\"Page.Control.MouseAction.Bind\" xml:space=\"preserve\">\n    <value>Bind</value>\n  </data>\n  <data name=\"Page.Settings.Storage.ConfigRootPath\" xml:space=\"preserve\">\n    <value>Parent Folder of Configs</value>\n  </data>\n  <data name=\"Page.Settings.Storage\" xml:space=\"preserve\">\n    <value>Storage</value>\n  </data>\n  <data name=\"Note.Settings.Storage\" xml:space=\"preserve\">\n    <value>Note: change config folder need restart program. this operation only change location, no files will be copied or moved to avoid overwrite files unexpectedly. \nif you want reuse current configs, you may manually copy \"Related Content\" to the folder you choosed, then restart program.\nRelated Content: Settings.json, Profiles\\*.*</value>\n  </data>\n  <data name=\"Page.Settings.Storage.ChangeConfigPath\" xml:space=\"preserve\">\n    <value>Change...</value>\n  </data>\n  <data name=\"Page.Settings.ProfileManager\" xml:space=\"preserve\">\n    <value>Profiles</value>\n  </data>\n  <data name=\"Page.Settings.Menus.Duplicate\" xml:space=\"preserve\">\n    <value>Duplicate</value>\n  </data>\n  <data name=\"Page.Settings.Menus.Rename\" xml:space=\"preserve\">\n    <value>Rename</value>\n  </data>\n  <data name=\"Page.Settings.Menus.Delete\" xml:space=\"preserve\">\n    <value>Delete</value>\n  </data>\n  <data name=\"Dialogs.OK\" xml:space=\"preserve\">\n    <value>OK</value>\n  </data>\n  <data name=\"Dialogs.Cancel\" xml:space=\"preserve\">\n    <value>Cancel</value>\n  </data>\n  <data name=\"Page.General.Basics\" xml:space=\"preserve\">\n    <value>Basics</value>\n  </data>\n  <data name=\"Page.General.Navigation\" xml:space=\"preserve\">\n    <value>Navigation</value>\n  </data>\n  <data name=\"Page.General.Nav.HType\" xml:space=\"preserve\">\n    <value>Right end of row joins to left end of:</value>\n  </data>\n  <data name=\"Page.General.Cluster\" xml:space=\"preserve\">\n    <value>Cluster</value>\n  </data>\n  <data name=\"Page.General.TaskScheduler\" xml:space=\"preserve\">\n    <value>Task Scheduler</value>\n  </data>\n  <data name=\"Note.General.Label.TaskScheduler\" xml:space=\"preserve\">\n    <value>Note: more details such as delay of start can be set in</value>\n  </data>\n  <data name=\"Page.General.RunOnStartup\" xml:space=\"preserve\">\n    <value>Launch program at system startup.</value>\n  </data>\n  <data name=\"Page.General.Nav.H\" xml:space=\"preserve\">\n    <value>Enable circulation.</value>\n  </data>\n  <data name=\"Page.General.Nav.V\" xml:space=\"preserve\">\n    <value>Circulate vertically. (same col only)</value>\n  </data>\n  <data name=\"Page.General.HideMainViewIfItsShown\" xml:space=\"preserve\">\n    <value>When use hotkey rise the MainView, Close it if the MainView already shown.</value>\n  </data>\n  <data name=\"Page.General.NotificationOnVdChanged\" xml:space=\"preserve\">\n    <value>Show notification when Current virtual desktop changed.</value>\n  </data>\n  <data name=\"Page.General.ShowVDIndexOnTrayIcon\" xml:space=\"preserve\">\n    <value>Show virtual desktop index on Tray Icon.</value>\n  </data>\n  <data name=\"Page.General.HideOnStart\" xml:space=\"preserve\">\n    <value>Hide MainView when program start.</value>\n  </data>\n  <data name=\"Page.General.StyleOfVDIndexOnTrayIcon.0\" xml:space=\"preserve\">\n    <value>Default</value>\n  </data>\n  <data name=\"Page.General.StyleOfVDIndexOnTrayIcon.1\" xml:space=\"preserve\">\n    <value>High Contrast 1</value>\n  </data>\n  <data name=\"Page.General.StyleOfVDIndexOnTrayIcon.2\" xml:space=\"preserve\">\n    <value>High Contrast 2</value>\n  </data>\n  <data name=\"Note.Settings.Profiles\" xml:space=\"preserve\">\n    <value>Note: KeyBindings, MouseActions, LogConfigs and StorageConfigs are shared by all profiles(regardless of profiles). \nsome settings may need restart program to take effect.</value>\n  </data>\n  <data name=\"Page.General.Nav.HType.1\" xml:space=\"preserve\">\n    <value>Same row</value>\n  </data>\n  <data name=\"Page.General.Nav.HType.0\" xml:space=\"preserve\">\n    <value>Next row</value>\n  </data>\n  <data name=\"Menus.Commons.RunAsAdmin\" xml:space=\"preserve\">\n    <value>Run As Administrator</value>\n  </data>\n  <data name=\"Page.Control.MouseAction.WindowBindings\" xml:space=\"preserve\">\n    <value>First select the MouseAction from the left side of the 🖇️ icon, then choose a behavior from the right side of the 🖇️ icon, and finally bind.</value>\n  </data>\n  <data name=\"Page.Control.MouseAction.DesktopBindings\" xml:space=\"preserve\">\n    <value>First select the MouseAction from the left side of the 🖇️ icon, then choose a behavior from the right side of the 🖇️ icon, and finally bind.</value>\n  </data>\n  <data name=\"Page.Control.MouseAction.ExpanderHeader\" xml:space=\"preserve\">\n    <value>Expand for details.</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Tag\" xml:space=\"preserve\">\n    <value>Tag(Group)</value>\n  </data>\n  <data name=\"Page.Rules.Weight\" xml:space=\"preserve\">\n    <value>Weight</value>\n  </data>\n  <data name=\"NavBar.About\" xml:space=\"preserve\">\n    <value>About</value>\n  </data>\n  <data name=\"Page.General.EnableWindowFilter\" xml:space=\"preserve\">\n    <value>When the MainView shown, [Double LShift] to open WindowFilter.</value>\n  </data>\n  <data name=\"Window.RuleDefinition\" xml:space=\"preserve\">\n    <value>Rule Definition</value>\n  </data>\n</root>"
  },
  {
    "path": "WPF/ControlPanel/Resources/Langs.zh-Hans.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"NavBar.Logs\" xml:space=\"preserve\">\n    <value>日志</value>\n  </data>\n  <data name=\"logTabInfo\" xml:space=\"preserve\">\n    <value>信息</value>\n  </data>\n  <data name=\"logTabDebug\" xml:space=\"preserve\">\n    <value>调试</value>\n  </data>\n  <data name=\"logTabWarning\" xml:space=\"preserve\">\n    <value>警告</value>\n  </data>\n  <data name=\"NavBar.General\" xml:space=\"preserve\">\n    <value>通用</value>\n  </data>\n  <data name=\"logTab.Menu.Clear\" xml:space=\"preserve\">\n    <value>清空</value>\n  </data>\n  <data name=\"NavBar.UI\" xml:space=\"preserve\">\n    <value>界面</value>\n  </data>\n  <data name=\"NavBar.Settings\" xml:space=\"preserve\">\n    <value>设置</value>\n  </data>\n  <data name=\"NavBar.Theme\" xml:space=\"preserve\">\n    <value>主题</value>\n  </data>\n  <data name=\"NavBar.Rules\" xml:space=\"preserve\">\n    <value>规则</value>\n  </data>\n  <data name=\"NavBar.Plugins\" xml:space=\"preserve\">\n    <value>插件</value>\n  </data>\n  <data name=\"NavBar.Help\" xml:space=\"preserve\">\n    <value>帮助</value>\n  </data>\n  <data name=\"Page.Settings.Language\" xml:space=\"preserve\">\n    <value>语言</value>\n  </data>\n  <data name=\"logTabError\" xml:space=\"preserve\">\n    <value>错误</value>\n  </data>\n  <data name=\"logTabEvent\" xml:space=\"preserve\">\n    <value>事件</value>\n  </data>\n  <data name=\"logTabVerbose\" xml:space=\"preserve\">\n    <value>详细</value>\n  </data>\n  <data name=\"Page.Settings.Theme.Sys\" xml:space=\"preserve\">\n    <value>系统设置</value>\n  </data>\n  <data name=\"Page.Settings.Theme\" xml:space=\"preserve\">\n    <value>主题</value>\n  </data>\n  <data name=\"Page.Settings.Theme.Light\" xml:space=\"preserve\">\n    <value>浅色</value>\n  </data>\n  <data name=\"Page.Settings.Theme.Dark\" xml:space=\"preserve\">\n    <value>深色</value>\n  </data>\n  <data name=\"Menus.Commons.Theme.Change\" xml:space=\"preserve\">\n    <value>切换主题</value>\n  </data>\n  <data name=\"Page.Logs.IsPrintLogs\" xml:space=\"preserve\">\n    <value>在 GUI 中显示日志</value>\n  </data>\n  <data name=\"Menus.Logs.OpenLogsDir\" xml:space=\"preserve\">\n    <value>打开日志文件夹...</value>\n  </data>\n  <data name=\"Menus.Logs.ClearAll\" xml:space=\"preserve\">\n    <value>清空所有日志</value>\n  </data>\n  <data name=\"Menus.Commons.Close\" xml:space=\"preserve\">\n    <value>关闭此窗口</value>\n  </data>\n  <data name=\"Menus.Commons.Restart\" xml:space=\"preserve\">\n    <value>重启</value>\n  </data>\n  <data name=\"Menus.Commons.Shutdown\" xml:space=\"preserve\">\n    <value>退出程序</value>\n  </data>\n  <data name=\"Page.Plugins.Author\" xml:space=\"preserve\">\n    <value>作者</value>\n  </data>\n  <data name=\"Page.Plugins.Close\" xml:space=\"preserve\">\n    <value>关闭</value>\n  </data>\n  <data name=\"Page.Plugins.Email\" xml:space=\"preserve\">\n    <value>邮箱</value>\n  </data>\n  <data name=\"Page.Plugins.Operations\" xml:space=\"preserve\">\n    <value>操作</value>\n  </data>\n  <data name=\"Page.Plugins.Name\" xml:space=\"preserve\">\n    <value>名称</value>\n  </data>\n  <data name=\"Page.Plugins.Restart\" xml:space=\"preserve\">\n    <value>重启</value>\n  </data>\n  <data name=\"Page.Plugins.Settings\" xml:space=\"preserve\">\n    <value>设置</value>\n  </data>\n  <data name=\"Page.Plugins.Version\" xml:space=\"preserve\">\n    <value>版本</value>\n  </data>\n  <data name=\"Page.Rules.Created\" xml:space=\"preserve\">\n    <value>创建时间</value>\n  </data>\n  <data name=\"Page.Rules.Updated\" xml:space=\"preserve\">\n    <value>更新时间</value>\n  </data>\n  <data name=\"Page.Rules.Add\" xml:space=\"preserve\">\n    <value>新建...</value>\n  </data>\n  <data name=\"Page.Rules.Clone\" xml:space=\"preserve\">\n    <value>复制</value>\n  </data>\n  <data name=\"Page.Rules.Delete\" xml:space=\"preserve\">\n    <value>删除(Del)</value>\n  </data>\n  <data name=\"Page.Rules.Edit\" xml:space=\"preserve\">\n    <value>编辑(E)...</value>\n  </data>\n  <data name=\"Page.Rules.EditRule\" xml:space=\"preserve\">\n    <value>编辑规则</value>\n  </data>\n  <data name=\"Page.Rules.NewRule\" xml:space=\"preserve\">\n    <value>新建规则</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Enabled\" xml:space=\"preserve\">\n    <value>启用</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Basic\" xml:space=\"preserve\">\n    <value>基本信息</value>\n  </data>\n  <data name=\"Generic.Name\" xml:space=\"preserve\">\n    <value>名称</value>\n  </data>\n  <data name=\"Validation.Error.Required\" xml:space=\"preserve\">\n    <value>必填项</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Created\" xml:space=\"preserve\">\n    <value>创建时间</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Updated\" xml:space=\"preserve\">\n    <value>更新时间</value>\n  </data>\n  <data name=\"Page.Rules.Rule.WindowRules\" xml:space=\"preserve\">\n    <value>窗口规则</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Title\" xml:space=\"preserve\">\n    <value>窗口标题</value>\n  </data>\n  <data name=\"Page.Rules.Rule.ProcessName\" xml:space=\"preserve\">\n    <value>进程名</value>\n  </data>\n  <data name=\"Page.Rules.Rule.ProcessPath\" xml:space=\"preserve\">\n    <value>进程路径</value>\n  </data>\n  <data name=\"Page.Rules.Rule.WinInScreen\" xml:space=\"preserve\">\n    <value>窗口位于屏幕</value>\n  </data>\n  <data name=\"Page.Rules.Rule.WndClass\" xml:space=\"preserve\">\n    <value>窗口样式</value>\n  </data>\n  <data name=\"Page.Rules.Rule.CloseDefBox\" xml:space=\"preserve\">\n    <value>取消</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Save\" xml:space=\"preserve\">\n    <value>保存并关闭</value>\n  </data>\n  <data name=\"Page.Rules.Rule.CommandLine\" xml:space=\"preserve\">\n    <value>命令行</value>\n  </data>\n  <data name=\"Page.Rules.Rule.WindowActions\" xml:space=\"preserve\">\n    <value>窗口动作</value>\n  </data>\n  <data name=\"Page.Rules.Rule.MoveToDesktop\" xml:space=\"preserve\">\n    <value>移动到桌面</value>\n  </data>\n  <data name=\"Page.Rules.Rule.FollowWindow\" xml:space=\"preserve\">\n    <value>跟随窗口</value>\n  </data>\n  <data name=\"Page.Rules.Rule.PinApp\" xml:space=\"preserve\">\n    <value>在所有桌面上显示此应用的窗口</value>\n  </data>\n  <data name=\"Page.Rules.Rule.HideFromView\" xml:space=\"preserve\">\n    <value>从视图中隐藏</value>\n  </data>\n  <data name=\"Page.Rules.Rule.MoveToScreen\" xml:space=\"preserve\">\n    <value>移动到屏幕</value>\n  </data>\n  <data name=\"Page.UI.VdArrangement\" xml:space=\"preserve\">\n    <value>虚拟桌面摆放方式</value>\n  </data>\n  <data name=\"Page.UI.VdView\" xml:space=\"preserve\">\n    <value>虚拟桌面视图</value>\n  </data>\n  <data name=\"Page.UI.ShowVdName\" xml:space=\"preserve\">\n    <value>显示虚拟桌面名称</value>\n  </data>\n  <data name=\"Page.UI.ShowVdIndex\" xml:space=\"preserve\">\n    <value>显示虚拟桌面索引</value>\n  </data>\n  <data name=\"Page.UI.ShowVdIndex.ZeroBased\" xml:space=\"preserve\">\n    <value>0-基索引</value>\n  </data>\n  <data name=\"Page.UI.ShowVdIndex.OneBased\" xml:space=\"preserve\">\n    <value>1-基索引</value>\n  </data>\n  <data name=\"Note.DesktopArrangement\" xml:space=\"preserve\">\n    <value>注意：当且仅当虚拟桌面的数量是自然数[1,n]的平方时，才可以变换摆放方式；条件不满足时程序将自动重置为第一种摆放方式。</value>\n  </data>\n  <data name=\"Page.UI.Label.m0\" xml:space=\"preserve\">\n    <value>左上 ↘ 右下, 横向(行满换行)</value>\n  </data>\n  <data name=\"Page.UI.Label.m1\" xml:space=\"preserve\">\n    <value>右上 ↙ 左下, 横向</value>\n  </data>\n  <data name=\"Page.UI.Label.m2\" xml:space=\"preserve\">\n    <value>左下 ↗ 右上, 横向</value>\n  </data>\n  <data name=\"Page.UI.Label.m3\" xml:space=\"preserve\">\n    <value>右下 ↖ 左上, 横向</value>\n  </data>\n  <data name=\"Page.UI.Label.m4\" xml:space=\"preserve\">\n    <value>左上 ↘ 右下, 纵向(列满换列)</value>\n  </data>\n  <data name=\"Page.UI.Label.m5\" xml:space=\"preserve\">\n    <value>右上 ↙ 左下, 纵向</value>\n  </data>\n  <data name=\"Page.UI.Label.m6\" xml:space=\"preserve\">\n    <value>左下 ↗ 右上, 纵向</value>\n  </data>\n  <data name=\"Page.UI.Label.m7\" xml:space=\"preserve\">\n    <value>右下 ↖ 左上, 纵向</value>\n  </data>\n  <data name=\"NavBar.Control\" xml:space=\"preserve\">\n    <value>控制</value>\n  </data>\n  <data name=\"Page.Control.Keyboard\" xml:space=\"preserve\">\n    <value>键盘</value>\n  </data>\n  <data name=\"Page.Control.Mouse\" xml:space=\"preserve\">\n    <value>鼠标</value>\n  </data>\n  <data name=\"Page.Control.KB.RegSave\" xml:space=\"preserve\">\n    <value>注册并保存</value>\n  </data>\n  <data name=\"Page.Control.KB.Extra\" xml:space=\"preserve\">\n    <value>备用</value>\n  </data>\n  <data name=\"Page.Control.KB.ClearSave\" xml:space=\"preserve\">\n    <value>清除并保存</value>\n  </data>\n  <data name=\"Page.Rules.Tag\" xml:space=\"preserve\">\n    <value>标签(分组)</value>\n  </data>\n  <data name=\"Generic.Filter\" xml:space=\"preserve\">\n    <value>过滤</value>\n  </data>\n  <data name=\"Page.Control.MouseAction.Save\" xml:space=\"preserve\">\n    <value>保存</value>\n  </data>\n  <data name=\"Page.Control.MouseAction.Clear\" xml:space=\"preserve\">\n    <value>清除</value>\n  </data>\n  <data name=\"Page.Control.MouseButtons.Left\" xml:space=\"preserve\">\n    <value>左键</value>\n  </data>\n  <data name=\"Page.Control.MouseButtons.Middle\" xml:space=\"preserve\">\n    <value>中键</value>\n  </data>\n  <data name=\"Page.Control.MouseButtons.Right\" xml:space=\"preserve\">\n    <value>右键</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Op.=\" xml:space=\"preserve\">\n    <value>是</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Op.rim\" xml:space=\"preserve\">\n    <value>正则表达式</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Op.esw\" xml:space=\"preserve\">\n    <value>以...结尾</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Op.sc\" xml:space=\"preserve\">\n    <value>包含</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Op.ssw\" xml:space=\"preserve\">\n    <value>以...开头</value>\n  </data>\n  <data name=\"Page.Control.MouseAction.OnDesktop\" xml:space=\"preserve\">\n    <value>在主视图中的虚拟桌面上点击时</value>\n  </data>\n  <data name=\"Page.Control.MouseAction.OnThumb\" xml:space=\"preserve\">\n    <value>在主视图中的窗口缩略图上点击时</value>\n  </data>\n  <data name=\"Page.Control.MouseAction.Behavior\" xml:space=\"preserve\">\n    <value>🖇️</value>\n  </data>\n  <data name=\"Mouse.Action.WindowHideFromView\" xml:space=\"preserve\">\n    <value>从视图中隐藏</value>\n  </data>\n  <data name=\"Mouse.Action.DoNothing\" xml:space=\"preserve\">\n    <value>什么都不做</value>\n  </data>\n  <data name=\"Mouse.Action.DesktopVisibleAndCloseView\" xml:space=\"preserve\">\n    <value>切换桌面并关闭视图</value>\n  </data>\n  <data name=\"Mouse.Action.DesktopVisibleOnly\" xml:space=\"preserve\">\n    <value>仅切换桌面</value>\n  </data>\n  <data name=\"Mouse.Action.ContextMenu\" xml:space=\"preserve\">\n    <value>显示上下文菜单</value>\n  </data>\n  <data name=\"Mouse.Action.WindowActiveDesktopVisibleAndCloseView\" xml:space=\"preserve\">\n    <value>激活窗口，切换桌面并关闭视图</value>\n  </data>\n  <data name=\"Mouse.Action.WindowActiveDesktopVisibleOnly\" xml:space=\"preserve\">\n    <value>激活窗口，切换桌面</value>\n  </data>\n  <data name=\"Mouse.Action.WindowClose\" xml:space=\"preserve\">\n    <value>关闭窗口</value>\n  </data>\n  <data name=\"Mouse.Action.WindowShowForSelectedProcessOnly\" xml:space=\"preserve\">\n    <value>仅显示此程序的窗口</value>\n  </data>\n  <data name=\"Mouse.Action.WindowShowForSelectedProcessInSelectedDesktop\" xml:space=\"preserve\">\n    <value>仅显示所选桌面中的活动程序窗口</value>\n  </data>\n  <data name=\"Mouse.Action.DesktopShowForSelectedDesktop\" xml:space=\"preserve\">\n    <value>仅显示所选桌面</value>\n  </data>\n  <data name=\"Page.Control.Mouse.UseWheelSwitchDesktopWhenOnTaskbar\" xml:space=\"preserve\">\n    <value>当鼠标指针在任务栏上时，用滚轮切换虚拟桌面。</value>\n  </data>\n  <data name=\"Page.Control.Mouse.Wheel.Down\" xml:space=\"preserve\">\n    <value>SHIFT+上滚 =&gt; 导航到上面桌面</value>\n  </data>\n  <data name=\"Page.Control.Mouse.Wheel.SUp\" xml:space=\"preserve\">\n    <value>下滚 =&gt; 导航到右侧桌面</value>\n  </data>\n  <data name=\"Page.Control.Mouse.Wheel.Up\" xml:space=\"preserve\">\n    <value>上滚 =&gt; 导航到左侧桌面</value>\n  </data>\n  <data name=\"Page.Control.Mouse.Wheel.SDown\" xml:space=\"preserve\">\n    <value>SHIFT+下滚 =&gt; 导航到下面桌面</value>\n  </data>\n  <data name=\"Page.Control.MouseAction.Bind\" xml:space=\"preserve\">\n    <value>绑定</value>\n  </data>\n  <data name=\"Page.Settings.Storage.ConfigRootPath\" xml:space=\"preserve\">\n    <value>配置文件夹根路径</value>\n  </data>\n  <data name=\"Page.Settings.Storage\" xml:space=\"preserve\">\n    <value>存储</value>\n  </data>\n  <data name=\"Note.Settings.Storage\" xml:space=\"preserve\">\n    <value>注意：改变配置文件夹需要重启程序。此操作仅改变位置，不会复制或移动任何文件，以免文件被意外覆盖。\n如果你想复用当前的配置，可以手动复制\"相关内容\"到你选择的文件夹，然后重启程序。\n相关内容：Settings.json, Profiles\\*.*</value>\n  </data>\n  <data name=\"Page.Settings.Storage.ChangeConfigPath\" xml:space=\"preserve\">\n    <value>变更...</value>\n  </data>\n  <data name=\"Page.Settings.ProfileManager\" xml:space=\"preserve\">\n    <value>配置文件</value>\n  </data>\n  <data name=\"Page.Settings.Menus.Delete\" xml:space=\"preserve\">\n    <value>删除</value>\n  </data>\n  <data name=\"Page.Settings.Menus.Duplicate\" xml:space=\"preserve\">\n    <value>复制</value>\n  </data>\n  <data name=\"Page.Settings.Menus.Rename\" xml:space=\"preserve\">\n    <value>重命名</value>\n  </data>\n  <data name=\"Dialogs.Cancel\" xml:space=\"preserve\">\n    <value>取消</value>\n  </data>\n  <data name=\"Dialogs.OK\" xml:space=\"preserve\">\n    <value>确定</value>\n  </data>\n  <data name=\"Page.General.Basics\" xml:space=\"preserve\">\n    <value>基本</value>\n  </data>\n  <data name=\"Page.General.Navigation\" xml:space=\"preserve\">\n    <value>导航</value>\n  </data>\n  <data name=\"Page.General.Nav.HType\" xml:space=\"preserve\">\n    <value>导航到某个方向的边界时，继续沿该方向导航将：</value>\n  </data>\n  <data name=\"Page.General.Cluster\" xml:space=\"preserve\">\n    <value>杂项</value>\n  </data>\n  <data name=\"Page.General.TaskScheduler\" xml:space=\"preserve\">\n    <value>计划任务程序</value>\n  </data>\n  <data name=\"Note.General.Label.TaskScheduler\" xml:space=\"preserve\">\n    <value>注意：诸如启动延迟等细节可在此设置</value>\n  </data>\n  <data name=\"Page.General.RunOnStartup\" xml:space=\"preserve\">\n    <value>随系统启动。</value>\n  </data>\n  <data name=\"Page.General.Nav.H\" xml:space=\"preserve\">\n    <value>水平方向循环。</value>\n  </data>\n  <data name=\"Page.General.Nav.V\" xml:space=\"preserve\">\n    <value>垂直方向循环。(仅相同列)</value>\n  </data>\n  <data name=\"Page.General.HideMainViewIfItsShown\" xml:space=\"preserve\">\n    <value>当使用热键唤起主视图时，如果主视图已经显示，则关闭之。</value>\n  </data>\n  <data name=\"Page.General.HideOnStart\" xml:space=\"preserve\">\n    <value>程序启动时不显示主视图。</value>\n  </data>\n  <data name=\"Page.General.NotificationOnVdChanged\" xml:space=\"preserve\">\n    <value>切换虚拟桌面时显示通知。</value>\n  </data>\n  <data name=\"Page.General.ShowVDIndexOnTrayIcon\" xml:space=\"preserve\">\n    <value>在系统托盘图标上显示桌面索引。</value>\n  </data>\n  <data name=\"Page.General.StyleOfVDIndexOnTrayIcon.0\" xml:space=\"preserve\">\n    <value>默认</value>\n  </data>\n  <data name=\"Page.General.StyleOfVDIndexOnTrayIcon.1\" xml:space=\"preserve\">\n    <value>高对比度 1</value>\n  </data>\n  <data name=\"Page.General.StyleOfVDIndexOnTrayIcon.2\" xml:space=\"preserve\">\n    <value>高对比度 2</value>\n  </data>\n  <data name=\"Note.Settings.Profiles\" xml:space=\"preserve\">\n    <value>注意：快捷键绑定、鼠标动作、日志配置和存储配置由所有配置文件共享(不区分配置文件)。\n某些设置可能需要重启程序才生效。</value>\n  </data>\n  <data name=\"Page.General.Nav.HType.0\" xml:space=\"preserve\">\n    <value>切换到下一行</value>\n  </data>\n  <data name=\"Page.General.Nav.HType.1\" xml:space=\"preserve\">\n    <value>在同一行内循环</value>\n  </data>\n  <data name=\"Menus.Commons.RunAsAdmin\" xml:space=\"preserve\">\n    <value>以管理员身份运行程序</value>\n  </data>\n  <data name=\"Page.Control.MouseAction.WindowBindings\" xml:space=\"preserve\">\n    <value>先从 🖇️ 图标左侧选择鼠标动作，然后从 🖇️ 图标右侧选择行为，最后绑定。 </value>\n  </data>\n  <data name=\"Page.Control.MouseAction.DesktopBindings\" xml:space=\"preserve\">\n    <value>先从 🖇️ 图标左侧选择鼠标动作，然后从 🖇️ 图标右侧选择行为，最后绑定。 </value>\n  </data>\n  <data name=\"Page.Control.MouseAction.ExpanderHeader\" xml:space=\"preserve\">\n    <value>展开详情</value>\n  </data>\n  <data name=\"Page.Rules.Rule.Tag\" xml:space=\"preserve\">\n    <value>标签(分组)</value>\n  </data>\n  <data name=\"Page.Rules.Weight\" xml:space=\"preserve\">\n    <value>权重</value>\n  </data>\n  <data name=\"NavBar.About\" xml:space=\"preserve\">\n    <value>关于</value>\n  </data>\n  <data name=\"Page.General.EnableWindowFilter\" xml:space=\"preserve\">\n    <value>当主视图显示时，[双击左SHIFT]打开窗口过滤器。</value>\n  </data>\n  <data name=\"Window.RuleDefinition\" xml:space=\"preserve\">\n    <value>规则定义</value>\n  </data>\n  <data name=\"Page.Rules.Rule.PinWindow\" xml:space=\"preserve\">\n    <value>在所有桌面上显示此窗口</value>\n  </data>\n</root>"
  },
  {
    "path": "WPF/ControlPanel/RuleEditorWindow.xaml",
    "content": "﻿<Window x:Class=\"ControlPanel.RuleEditorWindow\"\n        xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n        xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n        xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n        xmlns:userControls=\"clr-namespace:ControlPanel.Pages.UserControls\"\n        xmlns:lex=\"http://wpflocalizeextension.codeplex.com\"\n        lex:LocalizeDictionary.OutputMissingKeys=\"True\"\n        lex:ResxLocalizationProvider.DefaultAssembly=\"ControlPanel\"\n        lex:ResxLocalizationProvider.DefaultDictionary=\"Langs\"\n        TextElement.Foreground=\"{DynamicResource MaterialDesignBody}\"\n        TextElement.FontWeight=\"Regular\"\n        TextElement.FontSize=\"14\"\n        TextOptions.TextFormattingMode=\"Ideal\"\n        TextOptions.TextRenderingMode=\"Auto\"\n        Background=\"{DynamicResource MaterialDesignPaper}\"\n        FontFamily=\"Segoe UI,Segoe UI Emoji,Segoe UI Symbol,Microsoft YaHei UI,Microsoft YaHei\"\n        WindowStartupLocation=\"CenterScreen\" Closing=\"RuleEditorWindow_OnClosing\"\n        Title=\"{lex:Loc Window.RuleDefinition}\" Height=\"700\" Width=\"1024\" Topmost=\"True\">\n\n    <Window.Resources>\n        <ResourceDictionary>\n            <ResourceDictionary.MergedDictionaries>\n                <materialDesign:BundledTheme BaseTheme=\"Light\" PrimaryColor=\"DeepPurple\" SecondaryColor=\"Lime\" />\n                <ResourceDictionary Source=\"pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml\" />\n            </ResourceDictionary.MergedDictionaries>\n        </ResourceDictionary>\n    </Window.Resources>\n\n    <Grid>\n        <userControls:RuleForm x:Name=\"RuleEditor\" Margin=\"10\" />\n    </Grid>\n</Window>"
  },
  {
    "path": "WPF/ControlPanel/RuleEditorWindow.xaml.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.ComponentModel;\nusing System.Diagnostics;\nusing System.Text;\nusing System.Windows;\nusing System.Windows.Forms;\nusing ControlPanel.ViewModels;\nusing VirtualSpace.Config;\nusing VirtualSpace.Config.Events.Entity;\nusing VirtualSpace.Helpers;\nusing Button = System.Windows.Controls.Button;\n\nnamespace ControlPanel;\n\npublic partial class RuleEditorWindow\n{\n    private static RuleEditorWindow? _instance;\n\n    private RuleEditorWindow()\n    {\n        InitializeComponent();\n        AddHandler( Button.ClickEvent, new RoutedEventHandler( ClickEventFromSubControl ) );\n    }\n\n    public static RuleEditorWindow Create( IntPtr handle )\n    {\n        _instance ??= new RuleEditorWindow();\n\n        _instance.RuleEditor.DataContext = new RuleTemplate\n        {\n            Id = Guid.Empty,\n            Enabled = true,\n            Action = new Behavior()\n        };\n\n        var sbTitle = new StringBuilder( Const.WindowTitleMaxLength );\n        _ = User32.GetWindowText( handle, sbTitle, sbTitle.Capacity );\n        _instance.RuleEditor.chb_Title.IsChecked = true;\n        _instance.RuleEditor.tb_Title.Text = sbTitle.ToString();\n\n        _ = User32.GetWindowThreadProcessId( handle, out var pId );\n        var process = Process.GetProcessById( pId );\n        _instance.RuleEditor.chb_ProcessName.IsChecked = true;\n        _instance.RuleEditor.tb_ProcessName.Text = process.ProcessName;\n\n        try\n        {\n            _instance.RuleEditor.tb_ProcessPath.Text = process.MainModule?.FileName;\n        }\n        catch ( Exception ex )\n        {\n            _instance.RuleEditor.chb_ProcessPath.IsChecked = false;\n            _instance.RuleEditor.tb_ProcessPath.Text = ex.Message;\n        }\n\n        try\n        {\n            _instance.RuleEditor.tb_CommandLine.Text = process.GetCommandLineArgs();\n        }\n        catch ( Exception ex )\n        {\n            _instance.RuleEditor.chb_CommandLine.IsChecked = false;\n            _instance.RuleEditor.tb_CommandLine.Text = ex.Message;\n        }\n\n        var sbCName = new StringBuilder( Const.WindowClassMaxLength );\n        _ = User32.GetClassName( handle, sbCName, sbCName.Capacity );\n        _instance.RuleEditor.tb_WndClass.Text = sbCName.ToString();\n\n        var allScreens = Screen.AllScreens;\n        var screen     = Screen.FromHandle( handle );\n        for ( var i = 0; i < allScreens.Length; i++ )\n        {\n            if ( screen.DeviceName == allScreens[i].DeviceName )\n            {\n                _instance.RuleEditor.cbb_WinInScreen.SelectedValue = i;\n                break;\n            }\n        }\n\n        _instance.RuleEditor.RuleListItemsSource = RulesViewModel.Instance.Rules;\n        _instance.RuleEditor.RuleDate.Visibility = Visibility.Hidden;\n\n        return _instance;\n    }\n\n    private void ClickEventFromSubControl( object sender, RoutedEventArgs e )\n    {\n        if ( e.OriginalSource is Button btn )\n        {\n            switch ( btn.Name )\n            {\n                case \"btnSave\":\n                case \"btnCloseDefBox\":\n\n                    e.Handled = true;\n                    Close();\n                    break;\n            }\n        }\n    }\n\n    private void RuleEditorWindow_OnClosing( object? sender, CancelEventArgs e )\n    {\n        e.Cancel = true;\n        Hide();\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Validation/Helper.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.Windows;\n\nnamespace ControlPanel.Validation;\n\npublic abstract class Helper\n{\n    public static bool HasError( DependencyProperty dp, params FrameworkElement[] controls )\n    {\n        foreach ( var control in controls )\n        {\n            var bd = control.GetBindingExpression( dp );\n            bd?.UpdateSource();\n            if ( bd?.ValidationError != null ) return true;\n        }\n\n        return false;\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Validation/NotEmptyValidationRule.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.Globalization;\nusing System.Windows.Controls;\nusing WPFLocalizeExtension.Engine;\n\nnamespace ControlPanel.Validation;\n\npublic class NotEmptyValidationRule : ValidationRule\n{\n    public override ValidationResult Validate( object? value, CultureInfo cultureInfo )\n    {\n        return string.IsNullOrWhiteSpace( ( value ?? \"\" ).ToString() )\n            ? new ValidationResult( false,\n                LocalizeDictionary.Instance.GetLocalizedObject( \"Validation.Error.Required\", null, LocalizeDictionary.Instance.Culture ).ToString() )\n            : ValidationResult.ValidResult;\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/Validation/NumberRangeValidationRule.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.Globalization;\nusing System.Windows.Controls;\n\nnamespace ControlPanel.Validation;\n\npublic class NumberRangeValidationRule : ValidationRule\n{\n    public override ValidationResult Validate( object? value, CultureInfo cultureInfo )\n    {\n        try\n        {\n            var v = int.Parse( value.ToString() );\n            if ( v < Min || v > Max )\n                return new ValidationResult( false, $\"{Min} - {Max}\" );\n        }\n        catch\n        {\n            return new ValidationResult( false, $\"{Min} - {Max}\" );\n        }\n\n        return ValidationResult.ValidResult;\n    }\n\n    public int Min { get; set; }\n    public int Max { get; set; }\n}"
  },
  {
    "path": "WPF/ControlPanel/ViewModels/ControlViewModel.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Windows;\nusing PropertyChanged;\nusing VirtualSpace.Config;\nusing VirtualSpace.Helpers;\n\nnamespace ControlPanel.ViewModels;\n\n[AddINotifyPropertyChangedInterface]\npublic partial class ControlViewModel : ViewModelBase\n{\n    public ControlViewModel()\n    {\n        _isInitialized = true;\n    }\n}\n\n[AddINotifyPropertyChangedInterface]\npublic partial class MouseActionModel : ViewModelBase\n{\n    public MouseActionModel()\n    {\n        _isInitialized = true;\n    }\n\n    private static List<object> GetMouseButtons()\n    {\n        return new List<object>\n        {\n            new {Value = \"Left\", Text = \"\"},\n            new {Value = \"Middle\", Text = \"\"},\n            new {Value = \"Right\", Text = \"\"}\n        };\n    }\n\n    public static List<object> DesktopActions { get; } = new List<object>\n    {\n        new {Value = MouseAction.Action.DoNothing.ToString(), Text = \"\"},\n        new {Value = MouseAction.Action.ContextMenu.ToString(), Text = \"\"},\n        new {Value = MouseAction.Action.DesktopVisibleAndCloseView.ToString(), Text = \"\"},\n        new {Value = MouseAction.Action.DesktopVisibleOnly.ToString(), Text = \"\"},\n        new {Value = MouseAction.Action.DesktopShowForSelectedDesktop.ToString(), Text = \"\"}\n    };\n\n    public static List<object> WindowActions { get; } = new List<object>\n    {\n        new {Value = MouseAction.Action.DoNothing.ToString(), Text = \"\"},\n        new {Value = MouseAction.Action.ContextMenu.ToString(), Text = \"\"},\n        new {Value = MouseAction.Action.WindowActiveDesktopVisibleAndCloseView.ToString(), Text = \"\"},\n        new {Value = MouseAction.Action.WindowActiveDesktopVisibleOnly.ToString(), Text = \"\"},\n        new {Value = MouseAction.Action.WindowClose.ToString(), Text = \"\"},\n        new {Value = MouseAction.Action.WindowHideFromView.ToString(), Text = \"\"},\n        new {Value = MouseAction.Action.WindowShowForSelectedProcessOnly.ToString(), Text = \"\"},\n        new {Value = MouseAction.Action.WindowShowForSelectedProcessInSelectedDesktop.ToString(), Text = \"\"},\n    };\n\n    public bool UseWheelSwitchDesktopWhenOnTaskbar { get; set; } = Manager.CurrentProfile.Mouse.UseWheelSwitchDesktopWhenOnTaskbar;\n\n    public void OnPropertyChanged( string propertyName, object before, object after )\n    {\n        var propertyChanged = PropertyChanged;\n        if ( propertyChanged == null ) return;\n        if ( _isInitialized && propertyName == nameof( UseWheelSwitchDesktopWhenOnTaskbar ) )\n        {\n            Manager.CurrentProfile.Mouse.UseWheelSwitchDesktopWhenOnTaskbar = (bool)after;\n            Manager.Save( reason: Manager.CurrentProfile.Mouse.UseWheelSwitchDesktopWhenOnTaskbar );\n            var msg = Manager.CurrentProfile.Mouse.UseWheelSwitchDesktopWhenOnTaskbar ? UserMessage.EnableMouseHook : UserMessage.DisableMouseHook;\n            User32.PostMessage( MainWindow.MainWindowHandle, WinMsg.WM_HOTKEY, (ulong)msg, 0 );\n        }\n\n        propertyChanged( this, new PropertyChangedEventArgs( propertyName ) );\n    }\n\n    public bool LWin     { get; set; }\n    public bool Ctrl     { get; set; }\n    public bool Alt      { get; set; }\n    public bool Shift    { get; set; }\n\n    public List<object> MouseButtons { get; set; } = GetMouseButtons();\n\n    public string MouseButton { get; set; } = \"Left\";\n\n    public void Clear()\n    {\n        LWin = Ctrl = Alt = Shift = false;\n        MouseButton = \"\";\n    }\n}\n\n[AddINotifyPropertyChangedInterface]\npublic partial class KeyBindingModel : ViewModelBase\n{\n    public KeyBindingModel()\n    {\n        BoxVisible = Visibility.Hidden;\n        _isInitialized = true;\n    }\n\n    public Visibility BoxVisible { get; set; }\n    public string     Path       { get; set; }\n    public string     Extra      { get; set; }\n    public bool       LWin       { get; set; }\n    public bool       Ctrl       { get; set; }\n    public bool       Alt        { get; set; }\n    public bool       Shift      { get; set; }\n    public string     Key        { get; set; }\n\n    public void Clear()\n    {\n        LWin = Ctrl = Alt = Shift = false;\n        Key = Const.Hotkey.NONE;\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/ViewModels/FullObservableCollection.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.Collections.Generic;\nusing System.Collections.ObjectModel;\nusing System.Collections.Specialized;\nusing System.ComponentModel;\n\nnamespace ControlPanel.ViewModels;\n\npublic sealed class FullObservableCollection<T> : ObservableCollection<T> where T : INotifyPropertyChanged\n{\n    private FullObservableCollection()\n    {\n        CollectionChanged += CollectionChangedHandler;\n    }\n\n    public FullObservableCollection( IEnumerable<T> normalList ) : this()\n    {\n        foreach ( var item in normalList )\n        {\n            Add( item );\n        }\n    }\n\n    private void CollectionChangedHandler( object? sender, NotifyCollectionChangedEventArgs e )\n    {\n        switch ( e.Action )\n        {\n            case NotifyCollectionChangedAction.Remove:\n            {\n                foreach ( T item in e.OldItems )\n                {\n                    item.PropertyChanged -= OnNotifyPropertyChanged;\n                }\n\n                return;\n            }\n            case NotifyCollectionChangedAction.Add:\n            {\n                foreach ( T item in e.NewItems )\n                {\n                    item.PropertyChanged += OnNotifyPropertyChanged;\n                }\n\n                break;\n            }\n        }\n    }\n\n    private void OnNotifyPropertyChanged( object? sender, PropertyChangedEventArgs e )\n    {\n        var args = new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Reset );\n        OnCollectionChanged( args );\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/ViewModels/GeneralViewModel.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing ControlPanel.Pages.Dialogs;\nusing MaterialDesignThemes.Wpf;\nusing PropertyChanged;\nusing VirtualSpace;\nusing VirtualSpace.Config;\nusing VirtualSpace.Config.Entity;\nusing VirtualSpace.Helpers;\n\nnamespace ControlPanel.ViewModels;\n\n[AddINotifyPropertyChangedInterface]\npublic partial class GeneralViewModel : ViewModelBase\n{\n    public GeneralViewModel()\n    {\n        NavH = Manager.CurrentProfile.Navigation.CirculationH;\n        NavV = Manager.CurrentProfile.Navigation.CirculationV;\n        NavHType = Manager.CurrentProfile.Navigation.CirculationHType;\n        RunOnStartup = TaskSchedulerHelper.IsTaskExistsByName( Const.AppName, Const.AppName ) ||\n                       TaskSchedulerHelper.IsTaskExistsByName( Const.AppName );\n        Cluster = new ClusterProxy( Manager.Configs.Cluster );\n        Manager.ProfileChanged += UpdateClusterProxy;\n        _isInitialized = true;\n    }\n\n    public void OnPropertyChanged( string propertyName, object before, object after )\n    {\n        var propertyChanged = PropertyChanged;\n        if ( propertyChanged == null ) return;\n        if ( _isInitialized )\n        {\n            switch ( propertyName )\n            {\n                case nameof( NavHType ):\n                case nameof( NavH ):\n                case nameof( NavV ):\n                    Manager.CurrentProfile.Navigation.CirculationH = NavH;\n                    Manager.CurrentProfile.Navigation.CirculationV = NavV;\n                    Manager.CurrentProfile.Navigation.CirculationHType = NavHType;\n                    Manager.Save( reason: Manager.CurrentProfile.Navigation );\n                    break;\n                case nameof( RunOnStartup ):\n                    if ( (bool)after && TaskSchedulerHelper.IsTaskExistsByName( Const.AppName, Const.AppName ) ) break;\n                    if ( !(bool)after && !TaskSchedulerHelper.IsTaskExistsByName( Const.AppName, Const.AppName ) ) break;\n                    try\n                    {\n                        if ( RunOnStartup )\n                        {\n                            TaskSchedulerHelper.CreateAutoRunTask( Const.AppName, Manager.AppPath, Const.AppName );\n                        }\n                        else\n                        {\n                            if ( TaskSchedulerHelper.IsTaskExistsByName( Const.AppName ) )\n                                TaskSchedulerHelper.DeleteTaskByName( Const.AppName );\n                            TaskSchedulerHelper.DeleteTaskByName( Const.AppName, Const.AppName );\n                        }\n                    }\n                    catch ( Exception e )\n                    {\n                        var view = new YesNoWithNote( Agent.Langs.GetString( e.Message ), PackIconKind.CloseOctagon );\n                        DialogHost.Show( view, \"GeneralDialog\" );\n                        RunOnStartup = !RunOnStartup;\n                    }\n\n                    break;\n            }\n        }\n\n        propertyChanged( this, new PropertyChangedEventArgs( propertyName ) );\n    }\n\n    public bool         NavH         { get; set; }\n    public int          NavHType     { get; set; }\n    public bool         NavV         { get; set; }\n    public bool         RunOnStartup { get; set; }\n    public ClusterProxy Cluster      { get; set; }\n\n    public List<object> NavHTypeList { get; set; } = new()\n    {\n        new {Value = Const.VirtualDesktop.NavHTypeNextRow, Text = \"\"},\n        new {Value = Const.VirtualDesktop.NavHTypeSameRow, Text = \"\"},\n    };\n\n    private void UpdateClusterProxy( object? sender, EventArgs eventArgs )\n    {\n        Cluster = new ClusterProxy( Manager.Configs.Cluster );\n    }\n\n    [AddINotifyPropertyChangedInterface]\n    public partial class ClusterProxy : Cluster\n    {\n        private bool _isInitialized;\n\n        public ClusterProxy( Cluster cluster )\n        {\n            _cluster = cluster;\n            HideMainViewIfItsShown = cluster.HideMainViewIfItsShown;\n            NotificationOnVdChanged = cluster.NotificationOnVdChanged;\n            ShowVDIndexOnTrayIcon = cluster.ShowVDIndexOnTrayIcon;\n            StyleOfVDIndexOnTrayIcon = cluster.StyleOfVDIndexOnTrayIcon;\n            HideOnStart = cluster.HideOnStart;\n            EnableWindowFilter = cluster.EnableWindowFilter;\n            _isInitialized = true;\n        }\n\n        private readonly Cluster _cluster;\n        public new       bool    HideMainViewIfItsShown   { get; set; }\n        public new       bool    NotificationOnVdChanged  { get; set; }\n        public new       bool    ShowVDIndexOnTrayIcon    { get; set; }\n        public new       int     StyleOfVDIndexOnTrayIcon { get; set; }\n        public new       bool    HideOnStart              { get; set; }\n        public new       bool    EnableWindowFilter       { get; set; }\n\n        public void OnPropertyChanged( string propertyName, object before, object after )\n        {\n            var propertyChanged = PropertyChanged;\n            if ( propertyChanged == null ) return;\n\n            if ( _isInitialized )\n            {\n                switch ( propertyName )\n                {\n                    case nameof( HideMainViewIfItsShown ):\n                        _cluster.HideMainViewIfItsShown = HideMainViewIfItsShown;\n                        break;\n                    case nameof( NotificationOnVdChanged ):\n                        _cluster.NotificationOnVdChanged = NotificationOnVdChanged;\n                        break;\n                    case nameof( ShowVDIndexOnTrayIcon ):\n                    case nameof( StyleOfVDIndexOnTrayIcon ):\n                        _cluster.ShowVDIndexOnTrayIcon = ShowVDIndexOnTrayIcon;\n                        _cluster.StyleOfVDIndexOnTrayIcon = StyleOfVDIndexOnTrayIcon;\n\n                        User32.PostMessage( MainWindow.MainWindowHandle, WinMsg.WM_HOTKEY, UserMessage.RefreshTrayIcon, 0 );\n                        break;\n                    case nameof( HideOnStart ):\n                        _cluster.HideOnStart = HideOnStart;\n                        break;\n                    case nameof( EnableWindowFilter ):\n                        _cluster.EnableWindowFilter = EnableWindowFilter;\n                        break;\n                }\n\n                Manager.Save( reason: Manager.Configs.Cluster );\n            }\n\n            propertyChanged( this, new PropertyChangedEventArgs( propertyName ) );\n        }\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/ViewModels/LogsViewModel.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.ComponentModel;\nusing PropertyChanged;\nusing VirtualSpace.AppLogs;\nusing VirtualSpace.Config;\n\nnamespace ControlPanel.ViewModels;\n\n[AddINotifyPropertyChangedInterface]\npublic partial class LogsViewModel : ViewModelBase\n{\n    public LogsViewModel()\n    {\n        IsPrintLogs = Manager.Configs.LogConfig.ShowLogsInGui;\n        _isInitialized = true;\n    }\n\n    public void OnPropertyChanged( string propertyName, object before, object after )\n    {\n        var propertyChanged = PropertyChanged;\n        if ( propertyChanged == null ) return;\n        if ( _isInitialized )\n        {\n            Logger.ShowLogsInGui = (bool)after;\n            Manager.Configs.LogConfig.ShowLogsInGui = Logger.ShowLogsInGui;\n            Manager.Save( reason: Manager.Configs.LogConfig.ShowLogsInGui );\n        }\n\n        propertyChanged( this, new PropertyChangedEventArgs( propertyName ) );\n    }\n\n    public bool IsPrintLogs { get; set; }\n}"
  },
  {
    "path": "WPF/ControlPanel/ViewModels/MenuContainerViewModel.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.Windows.Controls;\nusing MaterialDesignThemes.Wpf;\n\nnamespace ControlPanel.ViewModels;\n\npublic class MenuContainerViewModel : ViewModelBase\n{\n    public MenuContainerViewModel()\n    {\n        _isInitialized = true;\n    }\n\n    public string       HeaderKey { get; set; } = \"\";\n    public PackIconKind IconKind  { get; set; }\n\n    public UserControl? InjectContent { get; set; }\n}"
  },
  {
    "path": "WPF/ControlPanel/ViewModels/PluginsViewModel.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.Collections.ObjectModel;\nusing VirtualSpace.Plugin;\n\nnamespace ControlPanel.ViewModels;\n\npublic class PluginsViewModel\n{\n    public PluginsViewModel()\n    {\n        Plugins = new ObservableCollection<PluginInfo>( PluginHost.Plugins );\n    }\n\n    public ObservableCollection<PluginInfo> Plugins { get; set; }\n}"
  },
  {
    "path": "WPF/ControlPanel/ViewModels/RulesViewModel.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.Collections.Generic;\nusing System.Collections.Specialized;\nusing System.Linq;\nusing System.Text.Encodings.Web;\nusing System.Text.Json;\nusing System.Text.Json.Serialization;\nusing LinqExpressionBuilder;\nusing VirtualSpace.Config.Events.Entity;\nusing VirtualSpace.Config.Events.Expression;\nusing VirtualSpace.Helpers;\nusing VirtualSpace.VirtualDesktop.Api;\n\nnamespace ControlPanel.ViewModels;\n\npublic class RulesViewModel : ViewModelBase\n{\n    private static RulesViewModel?                        _instance;\n    public         FullObservableCollection<RuleTemplate> Rules;\n\n    private RulesViewModel()\n    {\n        _instance = this;\n        Rules = new FullObservableCollection<RuleTemplate>( Conditions.FetchRules() );\n        Rules.CollectionChanged += RulesOnListChanged;\n    }\n\n    public static RulesViewModel Instance => _instance ??= new RulesViewModel();\n\n    public static void ReloadRules()\n    {\n        if ( _instance == null ) return;\n\n        _instance.Rules.CollectionChanged -= _instance.RulesOnListChanged;\n        _instance.Rules = new FullObservableCollection<RuleTemplate>( Conditions.FetchRules() );\n        _instance.Rules.CollectionChanged += _instance.RulesOnListChanged;\n        Pages.Rules.ReloadRules();\n    }\n\n    private void RulesOnListChanged( object? sender, NotifyCollectionChangedEventArgs e )\n    {\n        Conditions.SaveRules( Rules.ToList() );\n    }\n\n    public static List<object> Operators => GetOperators();\n\n    private static List<object> GetOperators()\n    {\n        return new List<object>\n        {\n            new {Value = Keywords.Eq[0], text = \"\"},\n            new {Value = Keywords.StartsWith[0], Text = \"\"},\n            new {Value = Keywords.EndsWith[0], Text = \"\"},\n            new {Value = Keywords.Contains[0], Text = \"\"},\n            new {Value = Keywords.RegexIsMatch[0], Text = \"\"}\n        };\n    }\n\n    public static List<object> Screens => SysInfo.GetAllScreens();\n\n    public static List<object> Desktops\n    {\n        get\n        {\n            var desktops = new List<object>();\n            for ( var i = 0; i < DesktopWrapper.Count; i++ ) // system's order\n            {\n                desktops.Add( new {Value = i, Text = DesktopWrapper.DesktopNameFromIndex( i )} );\n            }\n\n            return desktops;\n        }\n    }\n\n    public static readonly JsonSerializerOptions? WriteOptions = new()\n    {\n        DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,\n        WriteIndented = true,\n        Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping\n    };\n}"
  },
  {
    "path": "WPF/ControlPanel/ViewModels/SettingsViewModel.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Collections.ObjectModel;\nusing System.ComponentModel;\nusing System.Globalization;\nusing PropertyChanged;\nusing VirtualSpace.Config;\nusing VirtualSpace.Helpers;\nusing WPFLocalizeExtension.Engine;\n\nnamespace ControlPanel.ViewModels;\n\n[AddINotifyPropertyChangedInterface]\npublic partial class SettingsViewModel : ViewModelBase\n{\n    private static SettingsViewModel? _instance;\n\n    private SettingsViewModel()\n    {\n        Theme = Manager.CurrentProfile.UI.Theme;\n        Language = Manager.CurrentProfile.UI.Language;\n        CurrentProfile = Manager.Configs.CurrentProfileName;\n        ProfileList = new ObservableCollection<object>();\n        foreach ( var profileName in Manager.Configs.Profiles.Keys )\n        {\n            ProfileList.Add( new {Value = profileName} );\n        }\n\n        _isInitialized = true;\n    }\n\n    public string ConfigRootPath { get; set; } = Manager.ConfigRootFolder;\n\n    public ObservableCollection<object> ProfileList    { get; set; }\n    public string                       CurrentProfile { get; set; }\n\n    public int    Theme    { get; set; }\n    public string Language { get; set; }\n\n    public static SettingsViewModel GetInstance()\n    {\n        return _instance ??= new SettingsViewModel();\n    }\n\n    public static event EventHandler? LanguageChanged;\n\n    public void OnPropertyChanged( string propertyName, object before, object after )\n    {\n        var propertyChanged = PropertyChanged;\n        if ( propertyChanged == null ) return;\n\n        if ( _isInitialized )\n        {\n            switch ( propertyName )\n            {\n                case nameof( Theme ):\n                    Manager.CurrentProfile.UI.Theme = (int)after;\n                    Manager.Save( reason: Manager.CurrentProfile.UI.Theme );\n                    break;\n                case nameof( CurrentProfile ):\n                    if ( string.IsNullOrEmpty( after.ToString() ) || before == after ) break;\n\n                    Manager.SwitchProfile( after.ToString() );\n                    RulesViewModel.ReloadRules();\n                    Theme = Manager.CurrentProfile.UI.Theme;\n                    Language = Manager.CurrentProfile.UI.Language;\n\n                    break;\n                case nameof( Language ):\n                    var lang = after.ToString();\n                    LocalizeDictionary.Instance.SetCurrentThreadCulture = true;\n                    LocalizeDictionary.Instance.Culture = new CultureInfo( lang );\n                    Manager.CurrentProfile.UI.Language = lang;\n                    Manager.Save( reason: Manager.CurrentProfile.UI.Language );\n                    User32.PostMessage( MainWindow.MainWindowHandle, WinMsg.WM_HOTKEY, UserMessage.UpdateTrayLang, 0 );\n                    LanguageChanged?.Invoke( null, EventArgs.Empty );\n                    break;\n            }\n        }\n\n        propertyChanged( this, new PropertyChangedEventArgs( propertyName ) );\n\n        if ( _isInitialized )\n        {\n            switch ( propertyName )\n            {\n                case nameof( Theme ):\n                    if ( before != after )\n                        MainWindow.UpdateTheme();\n                    break;\n            }\n        }\n    }\n}"
  },
  {
    "path": "WPF/ControlPanel/ViewModels/UIViewModel.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System.ComponentModel;\nusing PropertyChanged;\nusing VirtualSpace.Commons;\nusing VirtualSpace.Config;\nusing VirtualSpace.VirtualDesktop.Api;\n\nnamespace ControlPanel.ViewModels;\n\n[AddINotifyPropertyChangedInterface]\npublic partial class UIViewModel : ViewModelBase\n{\n    public UIViewModel()\n    {\n        VdArrangement = (int)Manager.CurrentProfile.UI.DesktopArrangement!;\n        VdCount = DesktopWrapper.Count;\n        ShowVdName = Manager.CurrentProfile.UI.ShowVdName;\n        ShowVdIndex = Manager.CurrentProfile.UI.ShowVdIndex;\n        ShowVdIndexType = Manager.CurrentProfile.UI.ShowVdIndexType;\n        _isInitialized = true;\n\n        DesktopManagerWrapper.DesktopCreatedEvent -= OnDesktopCreatedEvent;\n        DesktopManagerWrapper.DesktopCreatedEvent += OnDesktopCreatedEvent;\n        DesktopManagerWrapper.DesktopDeletedEvent -= OnDesktopDeletedEvent;\n        DesktopManagerWrapper.DesktopDeletedEvent += OnDesktopDeletedEvent;\n    }\n\n    private void OnDesktopCreatedEvent()\n    {\n        VdArrangement = (int)Manager.CurrentProfile.UI.DesktopArrangement!;\n        VdCount = DesktopWrapper.Count;\n    }\n\n    private void OnDesktopDeletedEvent( VirtualDesktopNotification vdn )\n    {\n        VdArrangement = (int)Manager.CurrentProfile.UI.DesktopArrangement!;\n        VdCount = DesktopWrapper.Count;\n    }\n\n    public void OnPropertyChanged( string propertyName, object before, object after )\n    {\n        var propertyChanged = PropertyChanged;\n        if ( propertyChanged == null ) return;\n        if ( _isInitialized )\n        {\n            switch ( propertyName )\n            {\n                case nameof( VdArrangement ):\n                    Manager.CurrentProfile.UI.DesktopArrangement = (int)after;\n                    Manager.Save( reason: Manager.CurrentProfile.UI.DesktopArrangement );\n                    break;\n                case nameof( ShowVdName ):\n                    Manager.CurrentProfile.UI.ShowVdName = (bool)after;\n                    Manager.Save( reason: Manager.CurrentProfile.UI.ShowVdName );\n                    break;\n                case nameof( ShowVdIndex ):\n                    Manager.CurrentProfile.UI.ShowVdIndex = (bool)after;\n                    Manager.Save( reason: Manager.CurrentProfile.UI.ShowVdIndex );\n                    break;\n                case nameof( ShowVdIndexType ):\n                    Manager.CurrentProfile.UI.ShowVdIndexType = (int)after;\n                    Manager.Save( reason: Manager.CurrentProfile.UI.ShowVdIndexType );\n                    break;\n            }\n        }\n\n        propertyChanged( this, new PropertyChangedEventArgs( propertyName ) );\n    }\n\n    public bool ShowVdName      { get; set; }\n    public bool ShowVdIndex     { get; set; }\n    public int  ShowVdIndexType { get; set; }\n    public int  VdArrangement   { get; set; }\n    public int  VdCount         { get; set; }\n}"
  },
  {
    "path": "WPF/ControlPanel/ViewModels/ViewModelBase.cs",
    "content": "﻿// Copyright (C) 2023 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nnamespace ControlPanel.ViewModels;\n\npublic abstract class ViewModelBase\n{\n    protected bool _isInitialized;\n}"
  },
  {
    "path": "WinForms/AppController/AppController.Designer.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nnamespace VirtualSpace\n{\n    partial class AppController\n    {\n        /// <summary>\n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null))\n            {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Windows Form Designer generated code\n\n        /// <summary>\n        /// Required method for Designer support - do not modify\n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            components = new System.ComponentModel.Container();\n            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AppController));\n            mainMenu = new System.Windows.Forms.MenuStrip();\n            fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            closeThisWindowToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            runAsAdministratorToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();\n            tsmiMainMenuRestart = new System.Windows.Forms.ToolStripMenuItem();\n            tsmiMainMenuQuit = new System.Windows.Forms.ToolStripMenuItem();\n            optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            langToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            logsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            showLogsInGuiToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            openLogFolderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            MT_Logs = new System.Windows.Forms.TabPage();\n            logTabs = new System.Windows.Forms.TabControl();\n            logTabInfo = new System.Windows.Forms.TabPage();\n            tbInfo = new System.Windows.Forms.TextBox();\n            logTabDebug = new System.Windows.Forms.TabPage();\n            tbDebug = new System.Windows.Forms.TextBox();\n            logTabVerbose = new System.Windows.Forms.TabPage();\n            tbVerbose = new System.Windows.Forms.TextBox();\n            logTabEvent = new System.Windows.Forms.TabPage();\n            tbEvent = new System.Windows.Forms.TextBox();\n            logTabWarning = new System.Windows.Forms.TabPage();\n            tbWarning = new System.Windows.Forms.TextBox();\n            logTabError = new System.Windows.Forms.TabPage();\n            tbError = new System.Windows.Forms.TextBox();\n            MT_General = new System.Windows.Forms.TabPage();\n            panel_General = new System.Windows.Forms.Panel();\n            tab_General = new System.Windows.Forms.TabControl();\n            tabPage_Genernal_Main = new System.Windows.Forms.TabPage();\n            gb_profiles = new System.Windows.Forms.GroupBox();\n            lb_profiles_note = new System.Windows.Forms.Label();\n            btn_profile_del = new System.Windows.Forms.Button();\n            btn_profile_rename = new System.Windows.Forms.Button();\n            btn_profile_dup = new System.Windows.Forms.Button();\n            cbb_profiles = new System.Windows.Forms.ComboBox();\n            gb_storage = new System.Windows.Forms.GroupBox();\n            lb_configRoot = new System.Windows.Forms.Label();\n            btn_chooseConfigRoot = new System.Windows.Forms.Button();\n            tb_configRoot = new System.Windows.Forms.TextBox();\n            lb_note_configRoot = new System.Windows.Forms.Label();\n            gb_general = new System.Windows.Forms.GroupBox();\n            llb_TaskScheduler = new System.Windows.Forms.LinkLabel();\n            lb_RunOnStartup = new System.Windows.Forms.Label();\n            chb_RunOnStartup = new System.Windows.Forms.CheckBox();\n            gb_nav = new System.Windows.Forms.GroupBox();\n            lb_nav_circle_h_type = new System.Windows.Forms.Label();\n            cb_nav_circle_h_type = new System.Windows.Forms.ComboBox();\n            cb_nav_circle_v = new System.Windows.Forms.CheckBox();\n            cb_nav_circle_h = new System.Windows.Forms.CheckBox();\n            gb_Cluster = new System.Windows.Forms.GroupBox();\n            rb_vdi_on_tray_style_2 = new System.Windows.Forms.RadioButton();\n            rb_vdi_on_tray_style_1 = new System.Windows.Forms.RadioButton();\n            rb_vdi_on_tray_style_0 = new System.Windows.Forms.RadioButton();\n            chb_HideOnStart = new System.Windows.Forms.CheckBox();\n            chb_showVDIndexOnTrayIcon = new System.Windows.Forms.CheckBox();\n            chb_notify_vd_changed = new System.Windows.Forms.CheckBox();\n            chb_HideMainViewIfItsShown = new System.Windows.Forms.CheckBox();\n            tabPage_Genernal_Keyboard = new System.Windows.Forms.TabPage();\n            tc_Keyboard = new System.Windows.Forms.TabControl();\n            tp_hk_main = new System.Windows.Forms.TabPage();\n            btn_hk_ClearAndSave = new System.Windows.Forms.Button();\n            btn_hk_RegAndSave = new System.Windows.Forms.Button();\n            tb_hk_tip = new System.Windows.Forms.TextBox();\n            lb_hk_func = new System.Windows.Forms.Label();\n            cb_hk_key = new System.Windows.Forms.ComboBox();\n            cb_hk_shift = new System.Windows.Forms.CheckBox();\n            cb_hk_alt = new System.Windows.Forms.CheckBox();\n            cb_hk_ctrl = new System.Windows.Forms.CheckBox();\n            cb_hk_win = new System.Windows.Forms.CheckBox();\n            tp_hk_extra = new System.Windows.Forms.TabPage();\n            lb_hk_extra = new System.Windows.Forms.Label();\n            tv_keyboard = new System.Windows.Forms.TreeView();\n            tabPage_Genernal_Mouse = new System.Windows.Forms.TabPage();\n            lb_MouseOnTaskbarSwitchDesktop2 = new System.Windows.Forms.Label();\n            tv_mouse = new System.Windows.Forms.TreeView();\n            lb_MouseOnTaskbarSwitchDesktop1 = new System.Windows.Forms.Label();\n            tc_Mouse = new System.Windows.Forms.TabControl();\n            tp_mouse_action = new System.Windows.Forms.TabPage();\n            btn_mouse_save = new System.Windows.Forms.Button();\n            lb_mouse_action = new System.Windows.Forms.Label();\n            cb_mouse_func = new System.Windows.Forms.ComboBox();\n            chb_MouseOnTaskbarSwitchDesktop = new System.Windows.Forms.CheckBox();\n            mainTabs = new System.Windows.Forms.TabControl();\n            MT_UI = new System.Windows.Forms.TabPage();\n            panel_UI = new System.Windows.Forms.Panel();\n            lb_ui_vd_view = new System.Windows.Forms.GroupBox();\n            rb_vd_index_1 = new System.Windows.Forms.RadioButton();\n            rb_vd_index_0 = new System.Windows.Forms.RadioButton();\n            chb_show_vd_index = new System.Windows.Forms.CheckBox();\n            chb_show_vd_name = new System.Windows.Forms.CheckBox();\n            gb_DesktopArrangement = new System.Windows.Forms.GroupBox();\n            tlp_DesktopArrangement = new System.Windows.Forms.TableLayoutPanel();\n            btn_m7 = new System.Windows.Forms.Button();\n            btn_m6 = new System.Windows.Forms.Button();\n            btn_m5 = new System.Windows.Forms.Button();\n            btn_m4 = new System.Windows.Forms.Button();\n            btn_m3 = new System.Windows.Forms.Button();\n            btn_m2 = new System.Windows.Forms.Button();\n            btn_m1 = new System.Windows.Forms.Button();\n            btn_m0 = new System.Windows.Forms.Button();\n            lb_DesktopArrangementNote = new System.Windows.Forms.Label();\n            MT_Rules = new System.Windows.Forms.TabPage();\n            gb_Rules = new System.Windows.Forms.GroupBox();\n            lv_Rules = new System.Windows.Forms.ListView();\n            lvc_Name = new System.Windows.Forms.ColumnHeader();\n            lvc_Created = new System.Windows.Forms.ColumnHeader();\n            lvc_Updated = new System.Windows.Forms.ColumnHeader();\n            btn_RuleEdit = new System.Windows.Forms.Button();\n            btn_RuleClone = new System.Windows.Forms.Button();\n            btn_RuleNew = new System.Windows.Forms.Button();\n            btn_RuleRemove = new System.Windows.Forms.Button();\n            gb_CurrentProfile = new System.Windows.Forms.GroupBox();\n            llb_goto_general = new System.Windows.Forms.LinkLabel();\n            cb_RuleProfiles = new System.Windows.Forms.ComboBox();\n            MT_Plugins = new System.Windows.Forms.TabPage();\n            gb_Plugins = new System.Windows.Forms.GroupBox();\n            lv_Plugins = new System.Windows.Forms.ListView();\n            lvc_PluginName = new System.Windows.Forms.ColumnHeader();\n            lvc_PluginVersion = new System.Windows.Forms.ColumnHeader();\n            lvc_PluginAuthor = new System.Windows.Forms.ColumnHeader();\n            lvc_PluginEmail = new System.Windows.Forms.ColumnHeader();\n            btn_PluginSettings = new System.Windows.Forms.Button();\n            MT_About = new System.Windows.Forms.TabPage();\n            lb_AppName = new System.Windows.Forms.Label();\n            llb_Company = new System.Windows.Forms.LinkLabel();\n            lbox_Env = new System.Windows.Forms.ListBox();\n            lb_Copyright = new System.Windows.Forms.Label();\n            lb_Version = new System.Windows.Forms.Label();\n            lbVersion = new System.Windows.Forms.Label();\n            pb_AboutLogo = new System.Windows.Forms.PictureBox();\n            logCMS = new System.Windows.Forms.ContextMenuStrip(components);\n            clearToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();\n            panel_Pages = new System.Windows.Forms.Panel();\n            ts_PageNav = new System.Windows.Forms.ToolStrip();\n            tsb_general = new System.Windows.Forms.ToolStripButton();\n            tsb_ui = new System.Windows.Forms.ToolStripButton();\n            tsb_rules = new System.Windows.Forms.ToolStripButton();\n            tsb_plugins = new System.Windows.Forms.ToolStripButton();\n            tsb_logs = new System.Windows.Forms.ToolStripButton();\n            tsb_about = new System.Windows.Forms.ToolStripButton();\n            panel_PageNav = new System.Windows.Forms.Panel();\n            panel_mask = new System.Windows.Forms.Panel();\n            mainStatusStrip = new System.Windows.Forms.StatusStrip();\n            tssl_main_tips = new System.Windows.Forms.ToolStripStatusLabel();\n            mainMenu.SuspendLayout();\n            MT_Logs.SuspendLayout();\n            logTabs.SuspendLayout();\n            logTabInfo.SuspendLayout();\n            logTabDebug.SuspendLayout();\n            logTabVerbose.SuspendLayout();\n            logTabEvent.SuspendLayout();\n            logTabWarning.SuspendLayout();\n            logTabError.SuspendLayout();\n            MT_General.SuspendLayout();\n            panel_General.SuspendLayout();\n            tab_General.SuspendLayout();\n            tabPage_Genernal_Main.SuspendLayout();\n            gb_profiles.SuspendLayout();\n            gb_storage.SuspendLayout();\n            gb_general.SuspendLayout();\n            gb_nav.SuspendLayout();\n            gb_Cluster.SuspendLayout();\n            tabPage_Genernal_Keyboard.SuspendLayout();\n            tc_Keyboard.SuspendLayout();\n            tp_hk_main.SuspendLayout();\n            tp_hk_extra.SuspendLayout();\n            tabPage_Genernal_Mouse.SuspendLayout();\n            tc_Mouse.SuspendLayout();\n            tp_mouse_action.SuspendLayout();\n            mainTabs.SuspendLayout();\n            MT_UI.SuspendLayout();\n            panel_UI.SuspendLayout();\n            lb_ui_vd_view.SuspendLayout();\n            gb_DesktopArrangement.SuspendLayout();\n            tlp_DesktopArrangement.SuspendLayout();\n            MT_Rules.SuspendLayout();\n            gb_Rules.SuspendLayout();\n            gb_CurrentProfile.SuspendLayout();\n            MT_Plugins.SuspendLayout();\n            gb_Plugins.SuspendLayout();\n            MT_About.SuspendLayout();\n            ((System.ComponentModel.ISupportInitialize)pb_AboutLogo).BeginInit();\n            logCMS.SuspendLayout();\n            panel_Pages.SuspendLayout();\n            ts_PageNav.SuspendLayout();\n            panel_PageNav.SuspendLayout();\n            mainStatusStrip.SuspendLayout();\n            SuspendLayout();\n            // \n            // mainMenu\n            // \n            resources.ApplyResources(mainMenu, \"mainMenu\");\n            mainMenu.ImageScalingSize = new System.Drawing.Size(24, 24);\n            mainMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { fileToolStripMenuItem, optionsToolStripMenuItem, helpToolStripMenuItem });\n            mainMenu.Name = \"mainMenu\";\n            // \n            // fileToolStripMenuItem\n            // \n            resources.ApplyResources(fileToolStripMenuItem, \"fileToolStripMenuItem\");\n            fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { closeThisWindowToolStripMenuItem, runAsAdministratorToolStripMenuItem, toolStripSeparator1, tsmiMainMenuRestart, tsmiMainMenuQuit });\n            fileToolStripMenuItem.Name = \"fileToolStripMenuItem\";\n            // \n            // closeThisWindowToolStripMenuItem\n            // \n            resources.ApplyResources(closeThisWindowToolStripMenuItem, \"closeThisWindowToolStripMenuItem\");\n            closeThisWindowToolStripMenuItem.Name = \"closeThisWindowToolStripMenuItem\";\n            closeThisWindowToolStripMenuItem.Click += closeThisWindowToolStripMenuItem_Click;\n            // \n            // runAsAdministratorToolStripMenuItem\n            // \n            resources.ApplyResources(runAsAdministratorToolStripMenuItem, \"runAsAdministratorToolStripMenuItem\");\n            runAsAdministratorToolStripMenuItem.Name = \"runAsAdministratorToolStripMenuItem\";\n            runAsAdministratorToolStripMenuItem.Click += runAsAdministratorToolStripMenuItem_Click;\n            // \n            // toolStripSeparator1\n            // \n            resources.ApplyResources(toolStripSeparator1, \"toolStripSeparator1\");\n            toolStripSeparator1.Name = \"toolStripSeparator1\";\n            // \n            // tsmiMainMenuRestart\n            // \n            resources.ApplyResources(tsmiMainMenuRestart, \"tsmiMainMenuRestart\");\n            tsmiMainMenuRestart.Name = \"tsmiMainMenuRestart\";\n            tsmiMainMenuRestart.Click += tsmiMainMenuRestart_Click;\n            // \n            // tsmiMainMenuQuit\n            // \n            resources.ApplyResources(tsmiMainMenuQuit, \"tsmiMainMenuQuit\");\n            tsmiMainMenuQuit.Name = \"tsmiMainMenuQuit\";\n            tsmiMainMenuQuit.Click += tsmiMainMenuQuit_Click;\n            // \n            // optionsToolStripMenuItem\n            // \n            resources.ApplyResources(optionsToolStripMenuItem, \"optionsToolStripMenuItem\");\n            optionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { langToolStripMenuItem, logsToolStripMenuItem });\n            optionsToolStripMenuItem.Name = \"optionsToolStripMenuItem\";\n            optionsToolStripMenuItem.DropDownOpening += optionsToolStripMenuItem_DropDownOpening;\n            // \n            // langToolStripMenuItem\n            // \n            resources.ApplyResources(langToolStripMenuItem, \"langToolStripMenuItem\");\n            langToolStripMenuItem.Name = \"langToolStripMenuItem\";\n            // \n            // logsToolStripMenuItem\n            // \n            resources.ApplyResources(logsToolStripMenuItem, \"logsToolStripMenuItem\");\n            logsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { showLogsInGuiToolStripMenuItem, openLogFolderToolStripMenuItem });\n            logsToolStripMenuItem.Name = \"logsToolStripMenuItem\";\n            // \n            // showLogsInGuiToolStripMenuItem\n            // \n            resources.ApplyResources(showLogsInGuiToolStripMenuItem, \"showLogsInGuiToolStripMenuItem\");\n            showLogsInGuiToolStripMenuItem.CheckOnClick = true;\n            showLogsInGuiToolStripMenuItem.Name = \"showLogsInGuiToolStripMenuItem\";\n            // \n            // openLogFolderToolStripMenuItem\n            // \n            resources.ApplyResources(openLogFolderToolStripMenuItem, \"openLogFolderToolStripMenuItem\");\n            openLogFolderToolStripMenuItem.Name = \"openLogFolderToolStripMenuItem\";\n            openLogFolderToolStripMenuItem.Click += openLogFolderToolStripMenuItem_Click;\n            // \n            // helpToolStripMenuItem\n            // \n            resources.ApplyResources(helpToolStripMenuItem, \"helpToolStripMenuItem\");\n            helpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { aboutToolStripMenuItem });\n            helpToolStripMenuItem.Name = \"helpToolStripMenuItem\";\n            // \n            // aboutToolStripMenuItem\n            // \n            resources.ApplyResources(aboutToolStripMenuItem, \"aboutToolStripMenuItem\");\n            aboutToolStripMenuItem.Name = \"aboutToolStripMenuItem\";\n            aboutToolStripMenuItem.Click += aboutToolStripMenuItem_Click;\n            // \n            // MT_Logs\n            // \n            resources.ApplyResources(MT_Logs, \"MT_Logs\");\n            MT_Logs.Controls.Add(logTabs);\n            MT_Logs.Name = \"MT_Logs\";\n            MT_Logs.UseVisualStyleBackColor = true;\n            // \n            // logTabs\n            // \n            resources.ApplyResources(logTabs, \"logTabs\");\n            logTabs.Controls.Add(logTabInfo);\n            logTabs.Controls.Add(logTabDebug);\n            logTabs.Controls.Add(logTabVerbose);\n            logTabs.Controls.Add(logTabEvent);\n            logTabs.Controls.Add(logTabWarning);\n            logTabs.Controls.Add(logTabError);\n            logTabs.Name = \"logTabs\";\n            logTabs.SelectedIndex = 0;\n            logTabs.Click += logTabs_Click;\n            // \n            // logTabInfo\n            // \n            resources.ApplyResources(logTabInfo, \"logTabInfo\");\n            logTabInfo.Controls.Add(tbInfo);\n            logTabInfo.Name = \"logTabInfo\";\n            logTabInfo.UseVisualStyleBackColor = true;\n            // \n            // tbInfo\n            // \n            resources.ApplyResources(tbInfo, \"tbInfo\");\n            tbInfo.Name = \"tbInfo\";\n            tbInfo.ReadOnly = true;\n            // \n            // logTabDebug\n            // \n            resources.ApplyResources(logTabDebug, \"logTabDebug\");\n            logTabDebug.Controls.Add(tbDebug);\n            logTabDebug.Name = \"logTabDebug\";\n            logTabDebug.UseVisualStyleBackColor = true;\n            // \n            // tbDebug\n            // \n            resources.ApplyResources(tbDebug, \"tbDebug\");\n            tbDebug.Name = \"tbDebug\";\n            tbDebug.ReadOnly = true;\n            // \n            // logTabVerbose\n            // \n            resources.ApplyResources(logTabVerbose, \"logTabVerbose\");\n            logTabVerbose.Controls.Add(tbVerbose);\n            logTabVerbose.Name = \"logTabVerbose\";\n            logTabVerbose.UseVisualStyleBackColor = true;\n            // \n            // tbVerbose\n            // \n            resources.ApplyResources(tbVerbose, \"tbVerbose\");\n            tbVerbose.Name = \"tbVerbose\";\n            tbVerbose.ReadOnly = true;\n            // \n            // logTabEvent\n            // \n            resources.ApplyResources(logTabEvent, \"logTabEvent\");\n            logTabEvent.Controls.Add(tbEvent);\n            logTabEvent.Name = \"logTabEvent\";\n            logTabEvent.UseVisualStyleBackColor = true;\n            // \n            // tbEvent\n            // \n            resources.ApplyResources(tbEvent, \"tbEvent\");\n            tbEvent.Name = \"tbEvent\";\n            tbEvent.ReadOnly = true;\n            // \n            // logTabWarning\n            // \n            resources.ApplyResources(logTabWarning, \"logTabWarning\");\n            logTabWarning.Controls.Add(tbWarning);\n            logTabWarning.Name = \"logTabWarning\";\n            logTabWarning.UseVisualStyleBackColor = true;\n            // \n            // tbWarning\n            // \n            resources.ApplyResources(tbWarning, \"tbWarning\");\n            tbWarning.Name = \"tbWarning\";\n            tbWarning.ReadOnly = true;\n            // \n            // logTabError\n            // \n            resources.ApplyResources(logTabError, \"logTabError\");\n            logTabError.Controls.Add(tbError);\n            logTabError.Name = \"logTabError\";\n            logTabError.UseVisualStyleBackColor = true;\n            // \n            // tbError\n            // \n            resources.ApplyResources(tbError, \"tbError\");\n            tbError.Name = \"tbError\";\n            tbError.ReadOnly = true;\n            // \n            // MT_General\n            // \n            resources.ApplyResources(MT_General, \"MT_General\");\n            MT_General.Controls.Add(panel_General);\n            MT_General.Name = \"MT_General\";\n            MT_General.UseVisualStyleBackColor = true;\n            // \n            // panel_General\n            // \n            resources.ApplyResources(panel_General, \"panel_General\");\n            panel_General.Controls.Add(tab_General);\n            panel_General.Name = \"panel_General\";\n            // \n            // tab_General\n            // \n            resources.ApplyResources(tab_General, \"tab_General\");\n            tab_General.Controls.Add(tabPage_Genernal_Main);\n            tab_General.Controls.Add(tabPage_Genernal_Keyboard);\n            tab_General.Controls.Add(tabPage_Genernal_Mouse);\n            tab_General.Name = \"tab_General\";\n            tab_General.SelectedIndex = 0;\n            // \n            // tabPage_Genernal_Main\n            // \n            resources.ApplyResources(tabPage_Genernal_Main, \"tabPage_Genernal_Main\");\n            tabPage_Genernal_Main.Controls.Add(gb_profiles);\n            tabPage_Genernal_Main.Controls.Add(gb_storage);\n            tabPage_Genernal_Main.Controls.Add(gb_general);\n            tabPage_Genernal_Main.Controls.Add(gb_nav);\n            tabPage_Genernal_Main.Controls.Add(gb_Cluster);\n            tabPage_Genernal_Main.Name = \"tabPage_Genernal_Main\";\n            tabPage_Genernal_Main.UseVisualStyleBackColor = true;\n            // \n            // gb_profiles\n            // \n            resources.ApplyResources(gb_profiles, \"gb_profiles\");\n            gb_profiles.Controls.Add(lb_profiles_note);\n            gb_profiles.Controls.Add(btn_profile_del);\n            gb_profiles.Controls.Add(btn_profile_rename);\n            gb_profiles.Controls.Add(btn_profile_dup);\n            gb_profiles.Controls.Add(cbb_profiles);\n            gb_profiles.Name = \"gb_profiles\";\n            gb_profiles.TabStop = false;\n            // \n            // lb_profiles_note\n            // \n            resources.ApplyResources(lb_profiles_note, \"lb_profiles_note\");\n            lb_profiles_note.Name = \"lb_profiles_note\";\n            // \n            // btn_profile_del\n            // \n            resources.ApplyResources(btn_profile_del, \"btn_profile_del\");\n            btn_profile_del.Name = \"btn_profile_del\";\n            btn_profile_del.UseVisualStyleBackColor = true;\n            btn_profile_del.Click += btn_profile_del_Click;\n            // \n            // btn_profile_rename\n            // \n            resources.ApplyResources(btn_profile_rename, \"btn_profile_rename\");\n            btn_profile_rename.Name = \"btn_profile_rename\";\n            btn_profile_rename.UseVisualStyleBackColor = true;\n            btn_profile_rename.Click += btn_profile_rename_Click;\n            // \n            // btn_profile_dup\n            // \n            resources.ApplyResources(btn_profile_dup, \"btn_profile_dup\");\n            btn_profile_dup.Name = \"btn_profile_dup\";\n            btn_profile_dup.UseVisualStyleBackColor = true;\n            btn_profile_dup.Click += btn_profile_dup_Click;\n            // \n            // cbb_profiles\n            // \n            resources.ApplyResources(cbb_profiles, \"cbb_profiles\");\n            cbb_profiles.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            cbb_profiles.FormattingEnabled = true;\n            cbb_profiles.Name = \"cbb_profiles\";\n            // \n            // gb_storage\n            // \n            resources.ApplyResources(gb_storage, \"gb_storage\");\n            gb_storage.Controls.Add(lb_configRoot);\n            gb_storage.Controls.Add(btn_chooseConfigRoot);\n            gb_storage.Controls.Add(tb_configRoot);\n            gb_storage.Controls.Add(lb_note_configRoot);\n            gb_storage.Name = \"gb_storage\";\n            gb_storage.TabStop = false;\n            // \n            // lb_configRoot\n            // \n            resources.ApplyResources(lb_configRoot, \"lb_configRoot\");\n            lb_configRoot.Name = \"lb_configRoot\";\n            // \n            // btn_chooseConfigRoot\n            // \n            resources.ApplyResources(btn_chooseConfigRoot, \"btn_chooseConfigRoot\");\n            btn_chooseConfigRoot.Name = \"btn_chooseConfigRoot\";\n            btn_chooseConfigRoot.UseVisualStyleBackColor = true;\n            btn_chooseConfigRoot.Click += btn_chooseConfigRoot_Click;\n            // \n            // tb_configRoot\n            // \n            resources.ApplyResources(tb_configRoot, \"tb_configRoot\");\n            tb_configRoot.Name = \"tb_configRoot\";\n            tb_configRoot.ReadOnly = true;\n            // \n            // lb_note_configRoot\n            // \n            resources.ApplyResources(lb_note_configRoot, \"lb_note_configRoot\");\n            lb_note_configRoot.Name = \"lb_note_configRoot\";\n            // \n            // gb_general\n            // \n            resources.ApplyResources(gb_general, \"gb_general\");\n            gb_general.Controls.Add(llb_TaskScheduler);\n            gb_general.Controls.Add(lb_RunOnStartup);\n            gb_general.Controls.Add(chb_RunOnStartup);\n            gb_general.Name = \"gb_general\";\n            gb_general.TabStop = false;\n            // \n            // llb_TaskScheduler\n            // \n            resources.ApplyResources(llb_TaskScheduler, \"llb_TaskScheduler\");\n            llb_TaskScheduler.Name = \"llb_TaskScheduler\";\n            llb_TaskScheduler.TabStop = true;\n            llb_TaskScheduler.LinkClicked += llb_TaskScheduler_LinkClicked;\n            // \n            // lb_RunOnStartup\n            // \n            resources.ApplyResources(lb_RunOnStartup, \"lb_RunOnStartup\");\n            lb_RunOnStartup.Name = \"lb_RunOnStartup\";\n            // \n            // chb_RunOnStartup\n            // \n            resources.ApplyResources(chb_RunOnStartup, \"chb_RunOnStartup\");\n            chb_RunOnStartup.Name = \"chb_RunOnStartup\";\n            chb_RunOnStartup.UseVisualStyleBackColor = true;\n            chb_RunOnStartup.CheckedChanged += chb_RunOnStartup_CheckedChanged;\n            chb_RunOnStartup.VisibleChanged += chb_RunOnStartup_VisibleChanged;\n            // \n            // gb_nav\n            // \n            resources.ApplyResources(gb_nav, \"gb_nav\");\n            gb_nav.Controls.Add(lb_nav_circle_h_type);\n            gb_nav.Controls.Add(cb_nav_circle_h_type);\n            gb_nav.Controls.Add(cb_nav_circle_v);\n            gb_nav.Controls.Add(cb_nav_circle_h);\n            gb_nav.Name = \"gb_nav\";\n            gb_nav.TabStop = false;\n            // \n            // lb_nav_circle_h_type\n            // \n            resources.ApplyResources(lb_nav_circle_h_type, \"lb_nav_circle_h_type\");\n            lb_nav_circle_h_type.Name = \"lb_nav_circle_h_type\";\n            // \n            // cb_nav_circle_h_type\n            // \n            resources.ApplyResources(cb_nav_circle_h_type, \"cb_nav_circle_h_type\");\n            cb_nav_circle_h_type.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            cb_nav_circle_h_type.FormattingEnabled = true;\n            cb_nav_circle_h_type.Name = \"cb_nav_circle_h_type\";\n            // \n            // cb_nav_circle_v\n            // \n            resources.ApplyResources(cb_nav_circle_v, \"cb_nav_circle_v\");\n            cb_nav_circle_v.Name = \"cb_nav_circle_v\";\n            cb_nav_circle_v.UseVisualStyleBackColor = true;\n            // \n            // cb_nav_circle_h\n            // \n            resources.ApplyResources(cb_nav_circle_h, \"cb_nav_circle_h\");\n            cb_nav_circle_h.Name = \"cb_nav_circle_h\";\n            cb_nav_circle_h.UseVisualStyleBackColor = true;\n            // \n            // gb_Cluster\n            // \n            resources.ApplyResources(gb_Cluster, \"gb_Cluster\");\n            gb_Cluster.Controls.Add(rb_vdi_on_tray_style_2);\n            gb_Cluster.Controls.Add(rb_vdi_on_tray_style_1);\n            gb_Cluster.Controls.Add(rb_vdi_on_tray_style_0);\n            gb_Cluster.Controls.Add(chb_HideOnStart);\n            gb_Cluster.Controls.Add(chb_showVDIndexOnTrayIcon);\n            gb_Cluster.Controls.Add(chb_notify_vd_changed);\n            gb_Cluster.Controls.Add(chb_HideMainViewIfItsShown);\n            gb_Cluster.Name = \"gb_Cluster\";\n            gb_Cluster.TabStop = false;\n            // \n            // rb_vdi_on_tray_style_2\n            // \n            resources.ApplyResources(rb_vdi_on_tray_style_2, \"rb_vdi_on_tray_style_2\");\n            rb_vdi_on_tray_style_2.Name = \"rb_vdi_on_tray_style_2\";\n            rb_vdi_on_tray_style_2.TabStop = true;\n            rb_vdi_on_tray_style_2.UseVisualStyleBackColor = true;\n            // \n            // rb_vdi_on_tray_style_1\n            // \n            resources.ApplyResources(rb_vdi_on_tray_style_1, \"rb_vdi_on_tray_style_1\");\n            rb_vdi_on_tray_style_1.Name = \"rb_vdi_on_tray_style_1\";\n            rb_vdi_on_tray_style_1.TabStop = true;\n            rb_vdi_on_tray_style_1.UseVisualStyleBackColor = true;\n            // \n            // rb_vdi_on_tray_style_0\n            // \n            resources.ApplyResources(rb_vdi_on_tray_style_0, \"rb_vdi_on_tray_style_0\");\n            rb_vdi_on_tray_style_0.Name = \"rb_vdi_on_tray_style_0\";\n            rb_vdi_on_tray_style_0.TabStop = true;\n            rb_vdi_on_tray_style_0.UseVisualStyleBackColor = true;\n            // \n            // chb_HideOnStart\n            // \n            resources.ApplyResources(chb_HideOnStart, \"chb_HideOnStart\");\n            chb_HideOnStart.Name = \"chb_HideOnStart\";\n            chb_HideOnStart.UseVisualStyleBackColor = true;\n            // \n            // chb_showVDIndexOnTrayIcon\n            // \n            resources.ApplyResources(chb_showVDIndexOnTrayIcon, \"chb_showVDIndexOnTrayIcon\");\n            chb_showVDIndexOnTrayIcon.Name = \"chb_showVDIndexOnTrayIcon\";\n            chb_showVDIndexOnTrayIcon.UseVisualStyleBackColor = true;\n            // \n            // chb_notify_vd_changed\n            // \n            resources.ApplyResources(chb_notify_vd_changed, \"chb_notify_vd_changed\");\n            chb_notify_vd_changed.Name = \"chb_notify_vd_changed\";\n            chb_notify_vd_changed.UseVisualStyleBackColor = true;\n            // \n            // chb_HideMainViewIfItsShown\n            // \n            resources.ApplyResources(chb_HideMainViewIfItsShown, \"chb_HideMainViewIfItsShown\");\n            chb_HideMainViewIfItsShown.Name = \"chb_HideMainViewIfItsShown\";\n            chb_HideMainViewIfItsShown.UseVisualStyleBackColor = true;\n            // \n            // tabPage_Genernal_Keyboard\n            // \n            resources.ApplyResources(tabPage_Genernal_Keyboard, \"tabPage_Genernal_Keyboard\");\n            tabPage_Genernal_Keyboard.Controls.Add(tc_Keyboard);\n            tabPage_Genernal_Keyboard.Controls.Add(tv_keyboard);\n            tabPage_Genernal_Keyboard.Name = \"tabPage_Genernal_Keyboard\";\n            tabPage_Genernal_Keyboard.UseVisualStyleBackColor = true;\n            // \n            // tc_Keyboard\n            // \n            resources.ApplyResources(tc_Keyboard, \"tc_Keyboard\");\n            tc_Keyboard.Controls.Add(tp_hk_main);\n            tc_Keyboard.Controls.Add(tp_hk_extra);\n            tc_Keyboard.Name = \"tc_Keyboard\";\n            tc_Keyboard.SelectedIndex = 0;\n            // \n            // tp_hk_main\n            // \n            resources.ApplyResources(tp_hk_main, \"tp_hk_main\");\n            tp_hk_main.Controls.Add(btn_hk_ClearAndSave);\n            tp_hk_main.Controls.Add(btn_hk_RegAndSave);\n            tp_hk_main.Controls.Add(tb_hk_tip);\n            tp_hk_main.Controls.Add(lb_hk_func);\n            tp_hk_main.Controls.Add(cb_hk_key);\n            tp_hk_main.Controls.Add(cb_hk_shift);\n            tp_hk_main.Controls.Add(cb_hk_alt);\n            tp_hk_main.Controls.Add(cb_hk_ctrl);\n            tp_hk_main.Controls.Add(cb_hk_win);\n            tp_hk_main.Name = \"tp_hk_main\";\n            tp_hk_main.UseVisualStyleBackColor = true;\n            // \n            // btn_hk_ClearAndSave\n            // \n            resources.ApplyResources(btn_hk_ClearAndSave, \"btn_hk_ClearAndSave\");\n            btn_hk_ClearAndSave.Name = \"btn_hk_ClearAndSave\";\n            btn_hk_ClearAndSave.UseVisualStyleBackColor = true;\n            btn_hk_ClearAndSave.Click += btn_hk_ClearAndSave_Click;\n            // \n            // btn_hk_RegAndSave\n            // \n            resources.ApplyResources(btn_hk_RegAndSave, \"btn_hk_RegAndSave\");\n            btn_hk_RegAndSave.Name = \"btn_hk_RegAndSave\";\n            btn_hk_RegAndSave.UseVisualStyleBackColor = true;\n            btn_hk_RegAndSave.Click += btn_hk_RegAndSave_Click;\n            // \n            // tb_hk_tip\n            // \n            resources.ApplyResources(tb_hk_tip, \"tb_hk_tip\");\n            tb_hk_tip.Name = \"tb_hk_tip\";\n            // \n            // lb_hk_func\n            // \n            resources.ApplyResources(lb_hk_func, \"lb_hk_func\");\n            lb_hk_func.Name = \"lb_hk_func\";\n            // \n            // cb_hk_key\n            // \n            resources.ApplyResources(cb_hk_key, \"cb_hk_key\");\n            cb_hk_key.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            cb_hk_key.FormattingEnabled = true;\n            cb_hk_key.Items.AddRange(new object[] { resources.GetString(\"cb_hk_key.Items\"), resources.GetString(\"cb_hk_key.Items1\"), resources.GetString(\"cb_hk_key.Items2\"), resources.GetString(\"cb_hk_key.Items3\"), resources.GetString(\"cb_hk_key.Items4\"), resources.GetString(\"cb_hk_key.Items5\"), resources.GetString(\"cb_hk_key.Items6\"), resources.GetString(\"cb_hk_key.Items7\"), resources.GetString(\"cb_hk_key.Items8\"), resources.GetString(\"cb_hk_key.Items9\"), resources.GetString(\"cb_hk_key.Items10\"), resources.GetString(\"cb_hk_key.Items11\"), resources.GetString(\"cb_hk_key.Items12\"), resources.GetString(\"cb_hk_key.Items13\"), resources.GetString(\"cb_hk_key.Items14\"), resources.GetString(\"cb_hk_key.Items15\"), resources.GetString(\"cb_hk_key.Items16\"), resources.GetString(\"cb_hk_key.Items17\"), resources.GetString(\"cb_hk_key.Items18\"), resources.GetString(\"cb_hk_key.Items19\"), resources.GetString(\"cb_hk_key.Items20\"), resources.GetString(\"cb_hk_key.Items21\"), resources.GetString(\"cb_hk_key.Items22\"), resources.GetString(\"cb_hk_key.Items23\"), resources.GetString(\"cb_hk_key.Items24\"), resources.GetString(\"cb_hk_key.Items25\"), resources.GetString(\"cb_hk_key.Items26\"), resources.GetString(\"cb_hk_key.Items27\"), resources.GetString(\"cb_hk_key.Items28\"), resources.GetString(\"cb_hk_key.Items29\"), resources.GetString(\"cb_hk_key.Items30\"), resources.GetString(\"cb_hk_key.Items31\"), resources.GetString(\"cb_hk_key.Items32\"), resources.GetString(\"cb_hk_key.Items33\"), resources.GetString(\"cb_hk_key.Items34\"), resources.GetString(\"cb_hk_key.Items35\"), resources.GetString(\"cb_hk_key.Items36\"), resources.GetString(\"cb_hk_key.Items37\"), resources.GetString(\"cb_hk_key.Items38\"), resources.GetString(\"cb_hk_key.Items39\"), resources.GetString(\"cb_hk_key.Items40\"), resources.GetString(\"cb_hk_key.Items41\"), resources.GetString(\"cb_hk_key.Items42\"), resources.GetString(\"cb_hk_key.Items43\"), resources.GetString(\"cb_hk_key.Items44\"), resources.GetString(\"cb_hk_key.Items45\"), resources.GetString(\"cb_hk_key.Items46\"), resources.GetString(\"cb_hk_key.Items47\"), resources.GetString(\"cb_hk_key.Items48\"), resources.GetString(\"cb_hk_key.Items49\"), resources.GetString(\"cb_hk_key.Items50\"), resources.GetString(\"cb_hk_key.Items51\"), resources.GetString(\"cb_hk_key.Items52\"), resources.GetString(\"cb_hk_key.Items53\"), resources.GetString(\"cb_hk_key.Items54\"), resources.GetString(\"cb_hk_key.Items55\"), resources.GetString(\"cb_hk_key.Items56\"), resources.GetString(\"cb_hk_key.Items57\"), resources.GetString(\"cb_hk_key.Items58\"), resources.GetString(\"cb_hk_key.Items59\"), resources.GetString(\"cb_hk_key.Items60\"), resources.GetString(\"cb_hk_key.Items61\"), resources.GetString(\"cb_hk_key.Items62\"), resources.GetString(\"cb_hk_key.Items63\"), resources.GetString(\"cb_hk_key.Items64\"), resources.GetString(\"cb_hk_key.Items65\"), resources.GetString(\"cb_hk_key.Items66\"), resources.GetString(\"cb_hk_key.Items67\") });\n            cb_hk_key.Name = \"cb_hk_key\";\n            cb_hk_key.SelectedIndexChanged += cb_hk_key_SelectedIndexChanged;\n            // \n            // cb_hk_shift\n            // \n            resources.ApplyResources(cb_hk_shift, \"cb_hk_shift\");\n            cb_hk_shift.Name = \"cb_hk_shift\";\n            cb_hk_shift.UseVisualStyleBackColor = true;\n            cb_hk_shift.CheckedChanged += cb_hk_shift_CheckedChanged;\n            // \n            // cb_hk_alt\n            // \n            resources.ApplyResources(cb_hk_alt, \"cb_hk_alt\");\n            cb_hk_alt.Name = \"cb_hk_alt\";\n            cb_hk_alt.UseVisualStyleBackColor = true;\n            cb_hk_alt.CheckedChanged += cb_hk_alt_CheckedChanged;\n            // \n            // cb_hk_ctrl\n            // \n            resources.ApplyResources(cb_hk_ctrl, \"cb_hk_ctrl\");\n            cb_hk_ctrl.Name = \"cb_hk_ctrl\";\n            cb_hk_ctrl.UseVisualStyleBackColor = true;\n            cb_hk_ctrl.CheckedChanged += cb_hk_ctrl_CheckedChanged;\n            // \n            // cb_hk_win\n            // \n            resources.ApplyResources(cb_hk_win, \"cb_hk_win\");\n            cb_hk_win.Name = \"cb_hk_win\";\n            cb_hk_win.UseVisualStyleBackColor = true;\n            cb_hk_win.CheckedChanged += cb_hk_win_CheckedChanged;\n            // \n            // tp_hk_extra\n            // \n            resources.ApplyResources(tp_hk_extra, \"tp_hk_extra\");\n            tp_hk_extra.Controls.Add(lb_hk_extra);\n            tp_hk_extra.Name = \"tp_hk_extra\";\n            tp_hk_extra.UseVisualStyleBackColor = true;\n            // \n            // lb_hk_extra\n            // \n            resources.ApplyResources(lb_hk_extra, \"lb_hk_extra\");\n            lb_hk_extra.Name = \"lb_hk_extra\";\n            // \n            // tv_keyboard\n            // \n            resources.ApplyResources(tv_keyboard, \"tv_keyboard\");\n            tv_keyboard.Name = \"tv_keyboard\";\n            tv_keyboard.Nodes.AddRange(new System.Windows.Forms.TreeNode[] { (System.Windows.Forms.TreeNode)resources.GetObject(\"tv_keyboard.Nodes\"), (System.Windows.Forms.TreeNode)resources.GetObject(\"tv_keyboard.Nodes1\"), (System.Windows.Forms.TreeNode)resources.GetObject(\"tv_keyboard.Nodes2\") });\n            tv_keyboard.AfterSelect += tv_keyboard_AfterSelect;\n            // \n            // tabPage_Genernal_Mouse\n            // \n            resources.ApplyResources(tabPage_Genernal_Mouse, \"tabPage_Genernal_Mouse\");\n            tabPage_Genernal_Mouse.Controls.Add(lb_MouseOnTaskbarSwitchDesktop2);\n            tabPage_Genernal_Mouse.Controls.Add(tv_mouse);\n            tabPage_Genernal_Mouse.Controls.Add(lb_MouseOnTaskbarSwitchDesktop1);\n            tabPage_Genernal_Mouse.Controls.Add(tc_Mouse);\n            tabPage_Genernal_Mouse.Controls.Add(chb_MouseOnTaskbarSwitchDesktop);\n            tabPage_Genernal_Mouse.Name = \"tabPage_Genernal_Mouse\";\n            tabPage_Genernal_Mouse.UseVisualStyleBackColor = true;\n            // \n            // lb_MouseOnTaskbarSwitchDesktop2\n            // \n            resources.ApplyResources(lb_MouseOnTaskbarSwitchDesktop2, \"lb_MouseOnTaskbarSwitchDesktop2\");\n            lb_MouseOnTaskbarSwitchDesktop2.Name = \"lb_MouseOnTaskbarSwitchDesktop2\";\n            // \n            // tv_mouse\n            // \n            resources.ApplyResources(tv_mouse, \"tv_mouse\");\n            tv_mouse.Name = \"tv_mouse\";\n            tv_mouse.Nodes.AddRange(new System.Windows.Forms.TreeNode[] { (System.Windows.Forms.TreeNode)resources.GetObject(\"tv_mouse.Nodes\") });\n            tv_mouse.AfterSelect += tv_mouse_AfterSelect;\n            // \n            // lb_MouseOnTaskbarSwitchDesktop1\n            // \n            resources.ApplyResources(lb_MouseOnTaskbarSwitchDesktop1, \"lb_MouseOnTaskbarSwitchDesktop1\");\n            lb_MouseOnTaskbarSwitchDesktop1.Name = \"lb_MouseOnTaskbarSwitchDesktop1\";\n            // \n            // tc_Mouse\n            // \n            resources.ApplyResources(tc_Mouse, \"tc_Mouse\");\n            tc_Mouse.Controls.Add(tp_mouse_action);\n            tc_Mouse.Name = \"tc_Mouse\";\n            tc_Mouse.SelectedIndex = 0;\n            // \n            // tp_mouse_action\n            // \n            resources.ApplyResources(tp_mouse_action, \"tp_mouse_action\");\n            tp_mouse_action.Controls.Add(btn_mouse_save);\n            tp_mouse_action.Controls.Add(lb_mouse_action);\n            tp_mouse_action.Controls.Add(cb_mouse_func);\n            tp_mouse_action.Name = \"tp_mouse_action\";\n            tp_mouse_action.UseVisualStyleBackColor = true;\n            // \n            // btn_mouse_save\n            // \n            resources.ApplyResources(btn_mouse_save, \"btn_mouse_save\");\n            btn_mouse_save.Name = \"btn_mouse_save\";\n            btn_mouse_save.UseVisualStyleBackColor = true;\n            btn_mouse_save.Click += btn_mouse_save_Click;\n            // \n            // lb_mouse_action\n            // \n            resources.ApplyResources(lb_mouse_action, \"lb_mouse_action\");\n            lb_mouse_action.Name = \"lb_mouse_action\";\n            // \n            // cb_mouse_func\n            // \n            resources.ApplyResources(cb_mouse_func, \"cb_mouse_func\");\n            cb_mouse_func.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            cb_mouse_func.FormattingEnabled = true;\n            cb_mouse_func.Name = \"cb_mouse_func\";\n            // \n            // chb_MouseOnTaskbarSwitchDesktop\n            // \n            resources.ApplyResources(chb_MouseOnTaskbarSwitchDesktop, \"chb_MouseOnTaskbarSwitchDesktop\");\n            chb_MouseOnTaskbarSwitchDesktop.Name = \"chb_MouseOnTaskbarSwitchDesktop\";\n            chb_MouseOnTaskbarSwitchDesktop.UseVisualStyleBackColor = true;\n            // \n            // mainTabs\n            // \n            resources.ApplyResources(mainTabs, \"mainTabs\");\n            mainTabs.Controls.Add(MT_General);\n            mainTabs.Controls.Add(MT_UI);\n            mainTabs.Controls.Add(MT_Rules);\n            mainTabs.Controls.Add(MT_Plugins);\n            mainTabs.Controls.Add(MT_Logs);\n            mainTabs.Controls.Add(MT_About);\n            mainTabs.Name = \"mainTabs\";\n            mainTabs.SelectedIndex = 0;\n            mainTabs.SelectedIndexChanged += mainTabs_SelectedIndexChanged;\n            // \n            // MT_UI\n            // \n            resources.ApplyResources(MT_UI, \"MT_UI\");\n            MT_UI.Controls.Add(panel_UI);\n            MT_UI.Name = \"MT_UI\";\n            MT_UI.UseVisualStyleBackColor = true;\n            // \n            // panel_UI\n            // \n            resources.ApplyResources(panel_UI, \"panel_UI\");\n            panel_UI.Controls.Add(lb_ui_vd_view);\n            panel_UI.Controls.Add(gb_DesktopArrangement);\n            panel_UI.Name = \"panel_UI\";\n            // \n            // lb_ui_vd_view\n            // \n            resources.ApplyResources(lb_ui_vd_view, \"lb_ui_vd_view\");\n            lb_ui_vd_view.Controls.Add(rb_vd_index_1);\n            lb_ui_vd_view.Controls.Add(rb_vd_index_0);\n            lb_ui_vd_view.Controls.Add(chb_show_vd_index);\n            lb_ui_vd_view.Controls.Add(chb_show_vd_name);\n            lb_ui_vd_view.Name = \"lb_ui_vd_view\";\n            lb_ui_vd_view.TabStop = false;\n            // \n            // rb_vd_index_1\n            // \n            resources.ApplyResources(rb_vd_index_1, \"rb_vd_index_1\");\n            rb_vd_index_1.Name = \"rb_vd_index_1\";\n            rb_vd_index_1.TabStop = true;\n            rb_vd_index_1.UseVisualStyleBackColor = true;\n            // \n            // rb_vd_index_0\n            // \n            resources.ApplyResources(rb_vd_index_0, \"rb_vd_index_0\");\n            rb_vd_index_0.Name = \"rb_vd_index_0\";\n            rb_vd_index_0.TabStop = true;\n            rb_vd_index_0.UseVisualStyleBackColor = true;\n            // \n            // chb_show_vd_index\n            // \n            resources.ApplyResources(chb_show_vd_index, \"chb_show_vd_index\");\n            chb_show_vd_index.Name = \"chb_show_vd_index\";\n            chb_show_vd_index.UseVisualStyleBackColor = true;\n            // \n            // chb_show_vd_name\n            // \n            resources.ApplyResources(chb_show_vd_name, \"chb_show_vd_name\");\n            chb_show_vd_name.Name = \"chb_show_vd_name\";\n            chb_show_vd_name.UseVisualStyleBackColor = true;\n            // \n            // gb_DesktopArrangement\n            // \n            resources.ApplyResources(gb_DesktopArrangement, \"gb_DesktopArrangement\");\n            gb_DesktopArrangement.Controls.Add(tlp_DesktopArrangement);\n            gb_DesktopArrangement.Controls.Add(lb_DesktopArrangementNote);\n            gb_DesktopArrangement.Name = \"gb_DesktopArrangement\";\n            gb_DesktopArrangement.TabStop = false;\n            // \n            // tlp_DesktopArrangement\n            // \n            resources.ApplyResources(tlp_DesktopArrangement, \"tlp_DesktopArrangement\");\n            tlp_DesktopArrangement.Controls.Add(btn_m7, 3, 1);\n            tlp_DesktopArrangement.Controls.Add(btn_m6, 2, 1);\n            tlp_DesktopArrangement.Controls.Add(btn_m5, 1, 1);\n            tlp_DesktopArrangement.Controls.Add(btn_m4, 0, 1);\n            tlp_DesktopArrangement.Controls.Add(btn_m3, 3, 0);\n            tlp_DesktopArrangement.Controls.Add(btn_m2, 2, 0);\n            tlp_DesktopArrangement.Controls.Add(btn_m1, 1, 0);\n            tlp_DesktopArrangement.Controls.Add(btn_m0, 0, 0);\n            tlp_DesktopArrangement.Name = \"tlp_DesktopArrangement\";\n            // \n            // btn_m7\n            // \n            resources.ApplyResources(btn_m7, \"btn_m7\");\n            btn_m7.BackColor = System.Drawing.Color.Gainsboro;\n            btn_m7.Name = \"btn_m7\";\n            btn_m7.UseVisualStyleBackColor = false;\n            btn_m7.Click += tlp_DesktopArrangement_SubControlClicked;\n            // \n            // btn_m6\n            // \n            resources.ApplyResources(btn_m6, \"btn_m6\");\n            btn_m6.BackColor = System.Drawing.Color.Gainsboro;\n            btn_m6.Name = \"btn_m6\";\n            btn_m6.UseVisualStyleBackColor = false;\n            btn_m6.Click += tlp_DesktopArrangement_SubControlClicked;\n            // \n            // btn_m5\n            // \n            resources.ApplyResources(btn_m5, \"btn_m5\");\n            btn_m5.BackColor = System.Drawing.Color.Gainsboro;\n            btn_m5.Name = \"btn_m5\";\n            btn_m5.UseVisualStyleBackColor = false;\n            btn_m5.Click += tlp_DesktopArrangement_SubControlClicked;\n            // \n            // btn_m4\n            // \n            resources.ApplyResources(btn_m4, \"btn_m4\");\n            btn_m4.BackColor = System.Drawing.Color.Gainsboro;\n            btn_m4.Name = \"btn_m4\";\n            btn_m4.UseVisualStyleBackColor = false;\n            btn_m4.Click += tlp_DesktopArrangement_SubControlClicked;\n            // \n            // btn_m3\n            // \n            resources.ApplyResources(btn_m3, \"btn_m3\");\n            btn_m3.BackColor = System.Drawing.Color.Gainsboro;\n            btn_m3.Name = \"btn_m3\";\n            btn_m3.UseVisualStyleBackColor = false;\n            btn_m3.Click += tlp_DesktopArrangement_SubControlClicked;\n            // \n            // btn_m2\n            // \n            resources.ApplyResources(btn_m2, \"btn_m2\");\n            btn_m2.BackColor = System.Drawing.Color.Gainsboro;\n            btn_m2.Name = \"btn_m2\";\n            btn_m2.UseVisualStyleBackColor = false;\n            btn_m2.Click += tlp_DesktopArrangement_SubControlClicked;\n            // \n            // btn_m1\n            // \n            resources.ApplyResources(btn_m1, \"btn_m1\");\n            btn_m1.BackColor = System.Drawing.Color.Gainsboro;\n            btn_m1.Name = \"btn_m1\";\n            btn_m1.UseVisualStyleBackColor = false;\n            btn_m1.Click += tlp_DesktopArrangement_SubControlClicked;\n            // \n            // btn_m0\n            // \n            resources.ApplyResources(btn_m0, \"btn_m0\");\n            btn_m0.BackColor = System.Drawing.Color.MistyRose;\n            btn_m0.Name = \"btn_m0\";\n            btn_m0.UseVisualStyleBackColor = false;\n            btn_m0.Click += tlp_DesktopArrangement_SubControlClicked;\n            // \n            // lb_DesktopArrangementNote\n            // \n            resources.ApplyResources(lb_DesktopArrangementNote, \"lb_DesktopArrangementNote\");\n            lb_DesktopArrangementNote.ForeColor = System.Drawing.SystemColors.ControlText;\n            lb_DesktopArrangementNote.Name = \"lb_DesktopArrangementNote\";\n            // \n            // MT_Rules\n            // \n            resources.ApplyResources(MT_Rules, \"MT_Rules\");\n            MT_Rules.Controls.Add(gb_Rules);\n            MT_Rules.Controls.Add(gb_CurrentProfile);\n            MT_Rules.Name = \"MT_Rules\";\n            MT_Rules.UseVisualStyleBackColor = true;\n            // \n            // gb_Rules\n            // \n            resources.ApplyResources(gb_Rules, \"gb_Rules\");\n            gb_Rules.Controls.Add(lv_Rules);\n            gb_Rules.Controls.Add(btn_RuleEdit);\n            gb_Rules.Controls.Add(btn_RuleClone);\n            gb_Rules.Controls.Add(btn_RuleNew);\n            gb_Rules.Controls.Add(btn_RuleRemove);\n            gb_Rules.Name = \"gb_Rules\";\n            gb_Rules.TabStop = false;\n            // \n            // lv_Rules\n            // \n            resources.ApplyResources(lv_Rules, \"lv_Rules\");\n            lv_Rules.CheckBoxes = true;\n            lv_Rules.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { lvc_Name, lvc_Created, lvc_Updated });\n            lv_Rules.FullRowSelect = true;\n            lv_Rules.GridLines = true;\n            lv_Rules.MultiSelect = false;\n            lv_Rules.Name = \"lv_Rules\";\n            lv_Rules.UseCompatibleStateImageBehavior = false;\n            lv_Rules.View = System.Windows.Forms.View.Details;\n            lv_Rules.SelectedIndexChanged += lv_Rules_SelectedIndexChanged;\n            lv_Rules.VisibleChanged += lv_Rules_VisibleChanged;\n            lv_Rules.KeyDown += lv_Rules_KeyDown;\n            // \n            // lvc_Name\n            // \n            resources.ApplyResources(lvc_Name, \"lvc_Name\");\n            // \n            // lvc_Created\n            // \n            resources.ApplyResources(lvc_Created, \"lvc_Created\");\n            // \n            // lvc_Updated\n            // \n            resources.ApplyResources(lvc_Updated, \"lvc_Updated\");\n            // \n            // btn_RuleEdit\n            // \n            resources.ApplyResources(btn_RuleEdit, \"btn_RuleEdit\");\n            btn_RuleEdit.Name = \"btn_RuleEdit\";\n            btn_RuleEdit.UseVisualStyleBackColor = true;\n            btn_RuleEdit.Click += btn_RuleEdit_Click;\n            // \n            // btn_RuleClone\n            // \n            resources.ApplyResources(btn_RuleClone, \"btn_RuleClone\");\n            btn_RuleClone.Name = \"btn_RuleClone\";\n            btn_RuleClone.UseVisualStyleBackColor = true;\n            btn_RuleClone.Click += btn_RuleClone_Click;\n            // \n            // btn_RuleNew\n            // \n            resources.ApplyResources(btn_RuleNew, \"btn_RuleNew\");\n            btn_RuleNew.Name = \"btn_RuleNew\";\n            btn_RuleNew.UseVisualStyleBackColor = true;\n            btn_RuleNew.Click += btn_RuleNew_Click;\n            // \n            // btn_RuleRemove\n            // \n            resources.ApplyResources(btn_RuleRemove, \"btn_RuleRemove\");\n            btn_RuleRemove.Name = \"btn_RuleRemove\";\n            btn_RuleRemove.UseVisualStyleBackColor = true;\n            btn_RuleRemove.Click += btn_RuleRemove_Click;\n            // \n            // gb_CurrentProfile\n            // \n            resources.ApplyResources(gb_CurrentProfile, \"gb_CurrentProfile\");\n            gb_CurrentProfile.Controls.Add(llb_goto_general);\n            gb_CurrentProfile.Controls.Add(cb_RuleProfiles);\n            gb_CurrentProfile.Name = \"gb_CurrentProfile\";\n            gb_CurrentProfile.TabStop = false;\n            // \n            // llb_goto_general\n            // \n            resources.ApplyResources(llb_goto_general, \"llb_goto_general\");\n            llb_goto_general.Name = \"llb_goto_general\";\n            llb_goto_general.TabStop = true;\n            llb_goto_general.LinkClicked += llb_goto_general_LinkClicked;\n            // \n            // cb_RuleProfiles\n            // \n            resources.ApplyResources(cb_RuleProfiles, \"cb_RuleProfiles\");\n            cb_RuleProfiles.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            cb_RuleProfiles.FormattingEnabled = true;\n            cb_RuleProfiles.Name = \"cb_RuleProfiles\";\n            // \n            // MT_Plugins\n            // \n            resources.ApplyResources(MT_Plugins, \"MT_Plugins\");\n            MT_Plugins.Controls.Add(gb_Plugins);\n            MT_Plugins.Name = \"MT_Plugins\";\n            MT_Plugins.UseVisualStyleBackColor = true;\n            // \n            // gb_Plugins\n            // \n            resources.ApplyResources(gb_Plugins, \"gb_Plugins\");\n            gb_Plugins.Controls.Add(lv_Plugins);\n            gb_Plugins.Controls.Add(btn_PluginSettings);\n            gb_Plugins.Name = \"gb_Plugins\";\n            gb_Plugins.TabStop = false;\n            // \n            // lv_Plugins\n            // \n            resources.ApplyResources(lv_Plugins, \"lv_Plugins\");\n            lv_Plugins.CheckBoxes = true;\n            lv_Plugins.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { lvc_PluginName, lvc_PluginVersion, lvc_PluginAuthor, lvc_PluginEmail });\n            lv_Plugins.FullRowSelect = true;\n            lv_Plugins.GridLines = true;\n            lv_Plugins.MultiSelect = false;\n            lv_Plugins.Name = \"lv_Plugins\";\n            lv_Plugins.UseCompatibleStateImageBehavior = false;\n            lv_Plugins.View = System.Windows.Forms.View.Details;\n            lv_Plugins.SelectedIndexChanged += lv_Plugins_SelectedIndexChanged;\n            // \n            // lvc_PluginName\n            // \n            resources.ApplyResources(lvc_PluginName, \"lvc_PluginName\");\n            // \n            // lvc_PluginVersion\n            // \n            resources.ApplyResources(lvc_PluginVersion, \"lvc_PluginVersion\");\n            // \n            // lvc_PluginAuthor\n            // \n            resources.ApplyResources(lvc_PluginAuthor, \"lvc_PluginAuthor\");\n            // \n            // lvc_PluginEmail\n            // \n            resources.ApplyResources(lvc_PluginEmail, \"lvc_PluginEmail\");\n            // \n            // btn_PluginSettings\n            // \n            resources.ApplyResources(btn_PluginSettings, \"btn_PluginSettings\");\n            btn_PluginSettings.Name = \"btn_PluginSettings\";\n            btn_PluginSettings.UseVisualStyleBackColor = true;\n            btn_PluginSettings.Click += btn_PluginSettings_Click;\n            // \n            // MT_About\n            // \n            resources.ApplyResources(MT_About, \"MT_About\");\n            MT_About.Controls.Add(lb_AppName);\n            MT_About.Controls.Add(llb_Company);\n            MT_About.Controls.Add(lbox_Env);\n            MT_About.Controls.Add(lb_Copyright);\n            MT_About.Controls.Add(lb_Version);\n            MT_About.Controls.Add(lbVersion);\n            MT_About.Controls.Add(pb_AboutLogo);\n            MT_About.Name = \"MT_About\";\n            MT_About.UseVisualStyleBackColor = true;\n            MT_About.Paint += MT_About_Paint;\n            // \n            // lb_AppName\n            // \n            resources.ApplyResources(lb_AppName, \"lb_AppName\");\n            lb_AppName.Name = \"lb_AppName\";\n            // \n            // llb_Company\n            // \n            resources.ApplyResources(llb_Company, \"llb_Company\");\n            llb_Company.Name = \"llb_Company\";\n            llb_Company.TabStop = true;\n            llb_Company.LinkClicked += llb_Company_LinkClicked;\n            // \n            // lbox_Env\n            // \n            resources.ApplyResources(lbox_Env, \"lbox_Env\");\n            lbox_Env.FormattingEnabled = true;\n            lbox_Env.Name = \"lbox_Env\";\n            // \n            // lb_Copyright\n            // \n            resources.ApplyResources(lb_Copyright, \"lb_Copyright\");\n            lb_Copyright.Name = \"lb_Copyright\";\n            // \n            // lb_Version\n            // \n            resources.ApplyResources(lb_Version, \"lb_Version\");\n            lb_Version.Name = \"lb_Version\";\n            // \n            // lbVersion\n            // \n            resources.ApplyResources(lbVersion, \"lbVersion\");\n            lbVersion.Name = \"lbVersion\";\n            // \n            // pb_AboutLogo\n            // \n            resources.ApplyResources(pb_AboutLogo, \"pb_AboutLogo\");\n            pb_AboutLogo.Name = \"pb_AboutLogo\";\n            pb_AboutLogo.TabStop = false;\n            // \n            // logCMS\n            // \n            resources.ApplyResources(logCMS, \"logCMS\");\n            logCMS.ImageScalingSize = new System.Drawing.Size(24, 24);\n            logCMS.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { clearToolStripMenuItem });\n            logCMS.Name = \"logCMS\";\n            // \n            // clearToolStripMenuItem\n            // \n            resources.ApplyResources(clearToolStripMenuItem, \"clearToolStripMenuItem\");\n            clearToolStripMenuItem.Name = \"clearToolStripMenuItem\";\n            clearToolStripMenuItem.Click += clearToolStripMenuItem_Click;\n            // \n            // panel_Pages\n            // \n            resources.ApplyResources(panel_Pages, \"panel_Pages\");\n            panel_Pages.Controls.Add(mainTabs);\n            panel_Pages.Name = \"panel_Pages\";\n            // \n            // ts_PageNav\n            // \n            resources.ApplyResources(ts_PageNav, \"ts_PageNav\");\n            ts_PageNav.BackColor = System.Drawing.Color.White;\n            ts_PageNav.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;\n            ts_PageNav.ImageScalingSize = new System.Drawing.Size(24, 24);\n            ts_PageNav.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { tsb_general, tsb_ui, tsb_rules, tsb_plugins, tsb_logs, tsb_about });\n            ts_PageNav.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.VerticalStackWithOverflow;\n            ts_PageNav.Name = \"ts_PageNav\";\n            // \n            // tsb_general\n            // \n            resources.ApplyResources(tsb_general, \"tsb_general\");\n            tsb_general.Name = \"tsb_general\";\n            tsb_general.Padding = new System.Windows.Forms.Padding(10);\n            tsb_general.Tag = \"\";\n            tsb_general.Click += tsb_general_Click;\n            // \n            // tsb_ui\n            // \n            resources.ApplyResources(tsb_ui, \"tsb_ui\");\n            tsb_ui.Name = \"tsb_ui\";\n            tsb_ui.Padding = new System.Windows.Forms.Padding(10);\n            tsb_ui.Tag = \"\";\n            tsb_ui.Click += tsb_ui_Click;\n            // \n            // tsb_rules\n            // \n            resources.ApplyResources(tsb_rules, \"tsb_rules\");\n            tsb_rules.Name = \"tsb_rules\";\n            tsb_rules.Padding = new System.Windows.Forms.Padding(10);\n            tsb_rules.Tag = \"\";\n            tsb_rules.Click += tsb_rules_Click;\n            // \n            // tsb_plugins\n            // \n            resources.ApplyResources(tsb_plugins, \"tsb_plugins\");\n            tsb_plugins.Name = \"tsb_plugins\";\n            tsb_plugins.Padding = new System.Windows.Forms.Padding(10);\n            tsb_plugins.Tag = \"\";\n            tsb_plugins.Click += tsb_plugins_Click;\n            // \n            // tsb_logs\n            // \n            resources.ApplyResources(tsb_logs, \"tsb_logs\");\n            tsb_logs.Name = \"tsb_logs\";\n            tsb_logs.Padding = new System.Windows.Forms.Padding(10);\n            tsb_logs.Tag = \"\";\n            tsb_logs.Click += tsb_logs_Click;\n            // \n            // tsb_about\n            // \n            resources.ApplyResources(tsb_about, \"tsb_about\");\n            tsb_about.Name = \"tsb_about\";\n            tsb_about.Padding = new System.Windows.Forms.Padding(10);\n            tsb_about.Tag = \"\";\n            tsb_about.Click += tsb_about_Click;\n            // \n            // panel_PageNav\n            // \n            resources.ApplyResources(panel_PageNav, \"panel_PageNav\");\n            panel_PageNav.Controls.Add(ts_PageNav);\n            panel_PageNav.Name = \"panel_PageNav\";\n            // \n            // panel_mask\n            // \n            resources.ApplyResources(panel_mask, \"panel_mask\");\n            panel_mask.Name = \"panel_mask\";\n            // \n            // mainStatusStrip\n            // \n            resources.ApplyResources(mainStatusStrip, \"mainStatusStrip\");\n            mainStatusStrip.ImageScalingSize = new System.Drawing.Size(24, 24);\n            mainStatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { tssl_main_tips });\n            mainStatusStrip.Name = \"mainStatusStrip\";\n            mainStatusStrip.SizingGrip = false;\n            // \n            // tssl_main_tips\n            // \n            resources.ApplyResources(tssl_main_tips, \"tssl_main_tips\");\n            tssl_main_tips.Name = \"tssl_main_tips\";\n            // \n            // AppController\n            // \n            resources.ApplyResources(this, \"$this\");\n            AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            Controls.Add(mainStatusStrip);\n            Controls.Add(panel_mask);\n            Controls.Add(panel_PageNav);\n            Controls.Add(panel_Pages);\n            Controls.Add(mainMenu);\n            FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;\n            MainMenuStrip = mainMenu;\n            MaximizeBox = false;\n            MinimizeBox = false;\n            Name = \"AppController\";\n            ShowInTaskbar = false;\n            FormClosing += AppController_FormClosing;\n            mainMenu.ResumeLayout(false);\n            mainMenu.PerformLayout();\n            MT_Logs.ResumeLayout(false);\n            logTabs.ResumeLayout(false);\n            logTabInfo.ResumeLayout(false);\n            logTabInfo.PerformLayout();\n            logTabDebug.ResumeLayout(false);\n            logTabDebug.PerformLayout();\n            logTabVerbose.ResumeLayout(false);\n            logTabVerbose.PerformLayout();\n            logTabEvent.ResumeLayout(false);\n            logTabEvent.PerformLayout();\n            logTabWarning.ResumeLayout(false);\n            logTabWarning.PerformLayout();\n            logTabError.ResumeLayout(false);\n            logTabError.PerformLayout();\n            MT_General.ResumeLayout(false);\n            panel_General.ResumeLayout(false);\n            tab_General.ResumeLayout(false);\n            tabPage_Genernal_Main.ResumeLayout(false);\n            gb_profiles.ResumeLayout(false);\n            gb_storage.ResumeLayout(false);\n            gb_storage.PerformLayout();\n            gb_general.ResumeLayout(false);\n            gb_general.PerformLayout();\n            gb_nav.ResumeLayout(false);\n            gb_nav.PerformLayout();\n            gb_Cluster.ResumeLayout(false);\n            gb_Cluster.PerformLayout();\n            tabPage_Genernal_Keyboard.ResumeLayout(false);\n            tc_Keyboard.ResumeLayout(false);\n            tp_hk_main.ResumeLayout(false);\n            tp_hk_main.PerformLayout();\n            tp_hk_extra.ResumeLayout(false);\n            tabPage_Genernal_Mouse.ResumeLayout(false);\n            tabPage_Genernal_Mouse.PerformLayout();\n            tc_Mouse.ResumeLayout(false);\n            tp_mouse_action.ResumeLayout(false);\n            tp_mouse_action.PerformLayout();\n            mainTabs.ResumeLayout(false);\n            MT_UI.ResumeLayout(false);\n            panel_UI.ResumeLayout(false);\n            panel_UI.PerformLayout();\n            lb_ui_vd_view.ResumeLayout(false);\n            lb_ui_vd_view.PerformLayout();\n            gb_DesktopArrangement.ResumeLayout(false);\n            tlp_DesktopArrangement.ResumeLayout(false);\n            MT_Rules.ResumeLayout(false);\n            gb_Rules.ResumeLayout(false);\n            gb_CurrentProfile.ResumeLayout(false);\n            gb_CurrentProfile.PerformLayout();\n            MT_Plugins.ResumeLayout(false);\n            gb_Plugins.ResumeLayout(false);\n            MT_About.ResumeLayout(false);\n            MT_About.PerformLayout();\n            ((System.ComponentModel.ISupportInitialize)pb_AboutLogo).EndInit();\n            logCMS.ResumeLayout(false);\n            panel_Pages.ResumeLayout(false);\n            ts_PageNav.ResumeLayout(false);\n            ts_PageNav.PerformLayout();\n            panel_PageNav.ResumeLayout(false);\n            panel_PageNav.PerformLayout();\n            mainStatusStrip.ResumeLayout(false);\n            mainStatusStrip.PerformLayout();\n            ResumeLayout(false);\n            PerformLayout();\n        }\n\n        #endregion\n\n        private System.Windows.Forms.MenuStrip mainMenu;\n        private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;\n        private System.Windows.Forms.TabPage MT_Logs;\n        private System.Windows.Forms.TabPage MT_General;\n        private System.Windows.Forms.TabControl mainTabs;\n        private System.Windows.Forms.TabControl logTabs;\n        private System.Windows.Forms.TabPage logTabDebug;\n        private System.Windows.Forms.TabPage logTabInfo;\n        private System.Windows.Forms.TabPage logTabWarning;\n        private System.Windows.Forms.TabPage logTabError;\n        private System.Windows.Forms.TextBox tbInfo;\n        private System.Windows.Forms.TextBox tbWarning;\n        private System.Windows.Forms.TextBox tbError;\n        private System.Windows.Forms.TextBox tbDebug;\n        private System.Windows.Forms.ContextMenuStrip logCMS;\n        private System.Windows.Forms.ToolStripMenuItem clearToolStripMenuItem;\n        private System.Windows.Forms.TabPage logTabEvent;\n        private System.Windows.Forms.TextBox tbEvent;\n        private System.Windows.Forms.Panel panel_Pages;\n        private System.Windows.Forms.ToolStripMenuItem tsmiMainMenuQuit;\n        private System.Windows.Forms.ToolStripMenuItem optionsToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem langToolStripMenuItem;\n        private System.Windows.Forms.TabPage MT_UI;\n        private System.Windows.Forms.TabPage MT_Rules;\n        private System.Windows.Forms.ComboBox cb_RuleProfiles;\n        private System.Windows.Forms.ListView lv_Rules;\n        private System.Windows.Forms.ColumnHeader lvc_Name;\n        private System.Windows.Forms.ColumnHeader lvc_Created;\n        private System.Windows.Forms.ColumnHeader lvc_Updated;\n        private System.Windows.Forms.Button btn_RuleRemove;\n        private System.Windows.Forms.Button btn_RuleEdit;\n        private System.Windows.Forms.Button btn_RuleClone;\n        private System.Windows.Forms.Button btn_RuleNew;\n        private System.Windows.Forms.GroupBox gb_Rules;\n        private System.Windows.Forms.GroupBox gb_CurrentProfile;\n        private System.Windows.Forms.ToolStripMenuItem logsToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem showLogsInGuiToolStripMenuItem;\n        private System.Windows.Forms.ToolStrip ts_PageNav;\n        private System.Windows.Forms.ToolStripButton tsb_general;\n        private System.Windows.Forms.ToolStripButton tsb_ui;\n        private System.Windows.Forms.ToolStripButton tsb_rules;\n        private System.Windows.Forms.ToolStripButton tsb_plugins;\n        private System.Windows.Forms.ToolStripButton tsb_logs;\n        private System.Windows.Forms.Panel panel_PageNav;\n        private System.Windows.Forms.Panel panel_mask;\n        private System.Windows.Forms.TabPage MT_Plugins;\n        private System.Windows.Forms.StatusStrip mainStatusStrip;\n        private System.Windows.Forms.TabPage MT_About;\n        private System.Windows.Forms.LinkLabel llb_Company;\n        private System.Windows.Forms.ListBox lbox_Env;\n        private System.Windows.Forms.Label lb_Copyright;\n        private System.Windows.Forms.Label lb_Version;\n        private System.Windows.Forms.Label lbVersion;\n        private System.Windows.Forms.PictureBox pb_AboutLogo;\n        private System.Windows.Forms.ToolStripButton tsb_about;\n        private System.Windows.Forms.Label lb_AppName;\n        private System.Windows.Forms.GroupBox gb_Plugins;\n        private System.Windows.Forms.ListView lv_Plugins;\n        private System.Windows.Forms.ColumnHeader lvc_PluginName;\n        private System.Windows.Forms.ColumnHeader lvc_PluginVersion;\n        private System.Windows.Forms.ColumnHeader lvc_PluginAuthor;\n        private System.Windows.Forms.ColumnHeader lvc_PluginEmail;\n        private System.Windows.Forms.Button btn_PluginSettings;\n        private System.Windows.Forms.ToolStripMenuItem openLogFolderToolStripMenuItem;\n        private System.Windows.Forms.GroupBox gb_nav;\n        private System.Windows.Forms.CheckBox cb_nav_circle_v;\n        private System.Windows.Forms.CheckBox cb_nav_circle_h;\n        private System.Windows.Forms.Label lb_nav_circle_h_type;\n        private System.Windows.Forms.ComboBox cb_nav_circle_h_type;\n        private System.Windows.Forms.Panel panel_UI;\n        private System.Windows.Forms.GroupBox gb_DesktopArrangement;\n        private System.Windows.Forms.Label lb_DesktopArrangementNote;\n        private System.Windows.Forms.TableLayoutPanel tlp_DesktopArrangement;\n        private System.Windows.Forms.Button btn_m7;\n        private System.Windows.Forms.Button btn_m6;\n        private System.Windows.Forms.Button btn_m5;\n        private System.Windows.Forms.Button btn_m4;\n        private System.Windows.Forms.Button btn_m3;\n        private System.Windows.Forms.Button btn_m2;\n        private System.Windows.Forms.Button btn_m1;\n        private System.Windows.Forms.Button btn_m0;\n        private System.Windows.Forms.Panel panel_General;\n        private System.Windows.Forms.GroupBox gb_Cluster;\n        private System.Windows.Forms.TreeView tv_keyboard;\n        private System.Windows.Forms.TabControl tc_Keyboard;\n        private System.Windows.Forms.TabPage tp_hk_main;\n        private System.Windows.Forms.TextBox tb_hk_tip;\n        private System.Windows.Forms.ComboBox cb_hk_key;\n        private System.Windows.Forms.CheckBox cb_hk_shift;\n        private System.Windows.Forms.CheckBox cb_hk_alt;\n        private System.Windows.Forms.CheckBox cb_hk_ctrl;\n        private System.Windows.Forms.CheckBox cb_hk_win;\n        private System.Windows.Forms.TabPage tp_hk_extra;\n        private System.Windows.Forms.Label lb_hk_func;\n        private System.Windows.Forms.Label lb_hk_extra;\n        private System.Windows.Forms.ToolStripMenuItem closeThisWindowToolStripMenuItem;\n        private System.Windows.Forms.TreeView tv_mouse;\n        private System.Windows.Forms.TabControl tc_Mouse;\n        private System.Windows.Forms.TabPage tp_mouse_action;\n        private System.Windows.Forms.Button btn_mouse_save;\n        private System.Windows.Forms.Label lb_mouse_action;\n        private System.Windows.Forms.ComboBox cb_mouse_func;\n        private System.Windows.Forms.GroupBox lb_ui_vd_view;\n        private System.Windows.Forms.RadioButton rb_vd_index_1;\n        private System.Windows.Forms.RadioButton rb_vd_index_0;\n        private System.Windows.Forms.CheckBox chb_show_vd_index;\n        private System.Windows.Forms.CheckBox chb_show_vd_name;\n        private System.Windows.Forms.CheckBox chb_HideMainViewIfItsShown;\n        private System.Windows.Forms.CheckBox chb_notify_vd_changed;\n        private System.Windows.Forms.CheckBox chb_showVDIndexOnTrayIcon;\n        private System.Windows.Forms.CheckBox chb_HideOnStart;\n        private System.Windows.Forms.ToolStripMenuItem runAsAdministratorToolStripMenuItem;\n        private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;\n        private System.Windows.Forms.GroupBox gb_general;\n        private System.Windows.Forms.Label lb_RunOnStartup;\n        private System.Windows.Forms.CheckBox chb_RunOnStartup;\n        private System.Windows.Forms.LinkLabel llb_TaskScheduler;\n        private System.Windows.Forms.Button btn_hk_RegAndSave;\n        private System.Windows.Forms.Button btn_hk_ClearAndSave;\n        private System.Windows.Forms.CheckBox chb_MouseOnTaskbarSwitchDesktop;\n        private System.Windows.Forms.Label lb_MouseOnTaskbarSwitchDesktop2;\n        private System.Windows.Forms.Label lb_MouseOnTaskbarSwitchDesktop1;\n        private System.Windows.Forms.TabControl tab_General;\n        private System.Windows.Forms.TabPage tabPage_Genernal_Main;\n        private System.Windows.Forms.TabPage tabPage_Genernal_Keyboard;\n        private System.Windows.Forms.TabPage tabPage_Genernal_Mouse;\n        private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem;\n        private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem;\n        private System.Windows.Forms.TabPage logTabVerbose;\n        private System.Windows.Forms.TextBox tbVerbose;\n        private System.Windows.Forms.RadioButton rb_vdi_on_tray_style_2;\n        private System.Windows.Forms.RadioButton rb_vdi_on_tray_style_1;\n        private System.Windows.Forms.RadioButton rb_vdi_on_tray_style_0;\n        private System.Windows.Forms.GroupBox gb_storage;\n        private System.Windows.Forms.Button btn_chooseConfigRoot;\n        private System.Windows.Forms.TextBox tb_configRoot;\n        private System.Windows.Forms.Label lb_note_configRoot;\n        private System.Windows.Forms.Label lb_configRoot;\n        private System.Windows.Forms.ToolStripMenuItem tsmiMainMenuRestart;\n        private System.Windows.Forms.GroupBox gb_profiles;\n        private System.Windows.Forms.ComboBox cbb_profiles;\n        private System.Windows.Forms.Button btn_profile_del;\n        private System.Windows.Forms.Button btn_profile_rename;\n        private System.Windows.Forms.Button btn_profile_dup;\n        private System.Windows.Forms.ToolStripStatusLabel tssl_main_tips;\n        private System.Windows.Forms.LinkLabel llb_goto_general;\n        private System.Windows.Forms.Label lb_profiles_note;\n    }\n}"
  },
  {
    "path": "WinForms/AppController/AppController.DesktopArrangement.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Drawing;\nusing System.Windows.Forms;\nusing VirtualSpace.Config;\nusing VirtualSpace.Helpers;\n\nnamespace VirtualSpace\n{\n    public partial class AppController\n    {\n        private void tlp_DesktopArrangement_SubControlClicked( object sender, EventArgs e )\n        {\n            var btn        = sender as Button;\n            var selectedDa = btn.Name[^1..];\n\n            Manager.CurrentProfile.UI.DesktopArrangement = int.Parse( selectedDa );\n            Manager.Save( reason: Manager.CurrentProfile.UI.DesktopArrangement );\n\n            User32.PostMessage( _mainWindowHandle, WinMsg.WM_HOTKEY, UserMessage.DesktopArrangement, 0 );\n        }\n\n        public void RenderDesktopArrangementButtons( string selectedDa )\n        {\n            foreach ( var c in tlp_DesktopArrangement.Controls )\n            {\n                var i = c as Button;\n                i.BackColor = i.Name.EndsWith( selectedDa ) ? Color.MistyRose : Color.Gainsboro;\n            }\n        }\n    }\n}"
  },
  {
    "path": "WinForms/AppController/AppController.cluster.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.Diagnostics;\nusing System.Windows.Forms;\nusing VirtualSpace.Config;\nusing VirtualSpace.Helpers;\nusing ConfigManager = VirtualSpace.Config.Manager;\n\nnamespace VirtualSpace\n{\n    public partial class AppController\n    {\n        private void InitClusterConfig( bool resetEventHandlers = true )\n        {\n            if ( resetEventHandlers )\n            {\n                chb_HideMainViewIfItsShown.CheckedChanged -= chb_HideMainViewIfItsShown_CheckedChanged;\n                chb_notify_vd_changed.CheckedChanged -= chb_notify_vd_changed_CheckedChanged;\n                chb_showVDIndexOnTrayIcon.CheckedChanged -= chb_showVDIndexOnTrayIcon_CheckedChanged;\n                chb_HideOnStart.CheckedChanged -= chb_HideOnStart_CheckedChanged;\n                rb_vdi_on_tray_style_0.CheckedChanged -= rb_vdi_on_tray_style_0_CheckedChanged;\n                rb_vdi_on_tray_style_1.CheckedChanged -= rb_vdi_on_tray_style_0_CheckedChanged;\n                rb_vdi_on_tray_style_2.CheckedChanged -= rb_vdi_on_tray_style_0_CheckedChanged;\n            }\n\n            chb_HideMainViewIfItsShown.Checked = ConfigManager.Configs.Cluster.HideMainViewIfItsShown;\n            chb_notify_vd_changed.Checked = ConfigManager.Configs.Cluster.NotificationOnVdChanged;\n            chb_showVDIndexOnTrayIcon.Checked = ConfigManager.Configs.Cluster.ShowVDIndexOnTrayIcon;\n            chb_HideOnStart.Checked = ConfigManager.Configs.Cluster.HideOnStart;\n\n            switch ( ConfigManager.Configs.Cluster.StyleOfVDIndexOnTrayIcon )\n            {\n                case 0:\n                    rb_vdi_on_tray_style_0.Checked = true;\n                    break;\n                case 1:\n                    rb_vdi_on_tray_style_1.Checked = true;\n                    break;\n                case 2:\n                    rb_vdi_on_tray_style_2.Checked = true;\n                    break;\n                default:\n                    rb_vdi_on_tray_style_0.Checked = true;\n                    break;\n            }\n\n            if ( resetEventHandlers )\n            {\n                chb_HideMainViewIfItsShown.CheckedChanged += chb_HideMainViewIfItsShown_CheckedChanged;\n                chb_notify_vd_changed.CheckedChanged += chb_notify_vd_changed_CheckedChanged;\n                chb_showVDIndexOnTrayIcon.CheckedChanged += chb_showVDIndexOnTrayIcon_CheckedChanged;\n                chb_HideOnStart.CheckedChanged += chb_HideOnStart_CheckedChanged;\n                rb_vdi_on_tray_style_0.CheckedChanged += rb_vdi_on_tray_style_0_CheckedChanged;\n                rb_vdi_on_tray_style_1.CheckedChanged += rb_vdi_on_tray_style_0_CheckedChanged;\n                rb_vdi_on_tray_style_2.CheckedChanged += rb_vdi_on_tray_style_0_CheckedChanged;\n            }\n        }\n\n        private void rb_vdi_on_tray_style_0_CheckedChanged( object? sender, EventArgs e )\n        {\n            if ( !( (RadioButton)sender ).Checked ) return;\n            if ( rb_vdi_on_tray_style_0.Checked )\n            {\n                ConfigManager.Configs.Cluster.StyleOfVDIndexOnTrayIcon = 0;\n            }\n            else if ( rb_vdi_on_tray_style_1.Checked )\n            {\n                ConfigManager.Configs.Cluster.StyleOfVDIndexOnTrayIcon = 1;\n            }\n            else if ( rb_vdi_on_tray_style_2.Checked )\n            {\n                ConfigManager.Configs.Cluster.StyleOfVDIndexOnTrayIcon = 2;\n            }\n\n            NotifyHostRefreshTrayIcon();\n            ConfigManager.Save( reason: ConfigManager.Configs.Cluster.StyleOfVDIndexOnTrayIcon );\n        }\n\n        private void chb_HideMainViewIfItsShown_CheckedChanged( object? sender, EventArgs e )\n        {\n            ConfigManager.Configs.Cluster.HideMainViewIfItsShown = chb_HideMainViewIfItsShown.Checked;\n            ConfigManager.Save( reason: ConfigManager.Configs.Cluster.HideMainViewIfItsShown );\n        }\n\n        private void chb_notify_vd_changed_CheckedChanged( object? sender, EventArgs e )\n        {\n            ConfigManager.Configs.Cluster.NotificationOnVdChanged = chb_notify_vd_changed.Checked;\n            ConfigManager.Save( reason: ConfigManager.Configs.Cluster.NotificationOnVdChanged );\n        }\n\n        private void chb_showVDIndexOnTrayIcon_CheckedChanged( object? sender, EventArgs e )\n        {\n            NotifyHostRefreshTrayIcon();\n\n            ConfigManager.Configs.Cluster.ShowVDIndexOnTrayIcon = chb_showVDIndexOnTrayIcon.Checked;\n            ConfigManager.Save( reason: ConfigManager.Configs.Cluster.ShowVDIndexOnTrayIcon );\n        }\n\n        private void chb_HideOnStart_CheckedChanged( object? sender, EventArgs e )\n        {\n            ConfigManager.Configs.Cluster.HideOnStart = chb_HideOnStart.Checked;\n            ConfigManager.Save( reason: ConfigManager.Configs.Cluster.HideOnStart );\n        }\n\n        private void chb_RunOnStartup_CheckedChanged( object sender, EventArgs e )\n        {\n            if ( chb_RunOnStartup.Checked )\n            {\n                if ( TaskSchedulerHelper.IsTaskExistsByName( Const.AppName, Const.AppName ) ) return;\n                try\n                {\n                    TaskSchedulerHelper.CreateAutoRunTask( Const.AppName, Manager.AppPath, Const.AppName );\n                }\n                catch ( Exception ex )\n                {\n                    MessageBox.Show( Agent.Langs.GetString( ex.Message ) );\n                    chb_RunOnStartup.Checked = false;\n                }\n            }\n            else\n            {\n                if ( !TaskSchedulerHelper.IsTaskExistsByName( Const.AppName, Const.AppName ) ) return;\n                try\n                {\n                    TaskSchedulerHelper.DeleteTaskByName( Const.AppName, Const.AppName );\n                }\n                catch ( Exception ex )\n                {\n                    MessageBox.Show( Agent.Langs.GetString( ex.Message ) );\n                    chb_RunOnStartup.Checked = true;\n                }\n            }\n        }\n\n        private void chb_RunOnStartup_VisibleChanged( object sender, EventArgs e )\n        {\n            chb_RunOnStartup.Checked = TaskSchedulerHelper.IsTaskExistsByName( Const.AppName );\n        }\n\n        private void llb_TaskScheduler_LinkClicked( object sender, LinkLabelLinkClickedEventArgs e )\n        {\n            var psi = new ProcessStartInfo\n            {\n                FileName = \"taskschd.msc\",\n                UseShellExecute = true\n            };\n            Process.Start( psi );\n        }\n\n        private void NotifyHostRefreshTrayIcon()\n        {\n            User32.PostMessage( _mainWindowHandle, WinMsg.WM_HOTKEY, UserMessage.RefreshTrayIcon, 0 );\n        }\n    }\n}"
  },
  {
    "path": "WinForms/AppController/AppController.cs",
    "content": "﻿/* Copyright (C) 2021 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.ComponentModel;\nusing System.Diagnostics;\nusing System.Drawing;\nusing System.Globalization;\nusing System.IO;\nusing System.Reflection;\nusing System.Runtime.InteropServices;\nusing System.Windows.Forms;\nusing VirtualSpace.Config;\nusing VirtualSpace.Helpers;\nusing ConfigManager = VirtualSpace.Config.Manager;\n\nnamespace VirtualSpace\n{\n    public partial class AppController : Form, IAppController\n    {\n        private static readonly ComponentResourceManager Resources = new( typeof( AppController ) );\n        private static          AppController            _instance;\n        private                 IntPtr                   _mainWindowHandle;\n\n        public AppController()\n        {\n            Application.EnableVisualStyles();\n\n            var lang = ConfigManager.CurrentProfile.UI.Language;\n            if ( Agent.ValidLangs.ContainsKey( lang ) )\n            {\n                CultureInfo.CurrentCulture = new CultureInfo( lang );\n                CultureInfo.CurrentUICulture = new CultureInfo( lang );\n            }\n\n            _instance = this;\n\n            InitializeComponent();\n\n            base.Text = Const.Window.VS_CONTROLLER_TITLE;\n            pb_AboutLogo.Image = Images.BytesToBitmap( Agent.Images.GetObject( \"AboutLogo_2\" ) );\n\n            InitRuleListView();\n            InitPluginListView();\n            InitUiConfig();\n            InitClusterConfig();\n            InitMouseConfig();\n            InitStorageConfig();\n            InitProfileList();\n\n            CheckAdmin();\n\n            PickLogAndWrite( _cancelTokenSourceForLog.Token );\n        }\n\n        protected override CreateParams CreateParams\n        {\n            get\n            {\n                var cp = base.CreateParams;\n                cp.ExStyle |= 0x00000080; // WS_EX_TOOLWINDOW\n                cp.Style = unchecked(cp.Style | (int)0x80000000); // WS_POPUP\n                return cp;\n            }\n        }\n\n        public void BringToTop()\n        {\n            TopMost = true;\n\n            ReadRules();\n            ReadNavConfig();\n            InitKeyboardNodes();\n            InitMouseNodes();\n\n            Show();\n        }\n\n        public void SetMainWindowHandle( IntPtr handle )\n        {\n            _mainWindowHandle = handle;\n        }\n\n        public void Quit()\n        {\n            FormClosing -= AppController_FormClosing;\n            Close();\n        }\n\n        private void CheckAdmin()\n        {\n            if ( SysInfo.IsAdministrator )\n            {\n                runAsAdministratorToolStripMenuItem.Visible = false;\n                return;\n            }\n\n            var iconResult = new SHSTOCKICONINFO();\n            iconResult.cbSize = (uint)Marshal.SizeOf( iconResult );\n\n            _ = User32.SHGetStockIconInfo(\n                SHSTOCKICONID.SIID_SHIELD,\n                SHGSI.SHGSI_ICON | SHGSI.SHGSI_SMALLICON,\n                ref iconResult );\n            runAsAdministratorToolStripMenuItem.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;\n            var icon = Bitmap.FromHicon( iconResult.hIcon );\n            icon.MakeTransparent();\n            runAsAdministratorToolStripMenuItem.Image = icon;\n        }\n\n        private void AppController_FormClosing( object sender, FormClosingEventArgs e )\n        {\n            e.Cancel = true;\n            Hide();\n        }\n\n        private void tsb_general_Click( object sender, EventArgs e )\n        {\n            ts_PageNavButton_Click( sender, e );\n            mainTabs.SelectTab( 0 );\n        }\n\n        private void tsb_ui_Click( object sender, EventArgs e )\n        {\n            ts_PageNavButton_Click( sender, e );\n\n            RenderDesktopArrangementButtons( ConfigManager.CurrentProfile.UI.DesktopArrangement.ToString() );\n\n            mainTabs.SelectTab( 1 );\n        }\n\n        private void tsb_rules_Click( object sender, EventArgs e )\n        {\n            ts_PageNavButton_Click( sender, e );\n            mainTabs.SelectTab( 2 );\n        }\n\n        private void tsb_plugins_Click( object sender, EventArgs e )\n        {\n            ts_PageNavButton_Click( sender, e );\n            mainTabs.SelectTab( 3 );\n        }\n\n        private void tsb_logs_Click( object sender, EventArgs e )\n        {\n            ts_PageNavButton_Click( sender, e );\n            mainTabs.SelectTab( 4 );\n        }\n\n        private void tsb_about_Click( object sender, EventArgs e )\n        {\n            ts_PageNavButton_Click( sender, e );\n            mainTabs.SelectTab( 5 );\n        }\n\n        private void ts_PageNavButton_Click( object sender, EventArgs e )\n        {\n            foreach ( var item in ts_PageNav.Items )\n            {\n                var button = item as ToolStripButton;\n                button.Checked = sender == item;\n            }\n        }\n\n        private void llb_Company_LinkClicked( object sender, LinkLabelLinkClickedEventArgs e )\n        {\n            string url;\n            if ( e.Link.LinkData != null )\n                url = e.Link.LinkData.ToString();\n            else\n                url = llb_Company.Text.Substring( e.Link.Start, e.Link.Length );\n\n            if ( !url.Contains( \"://\" ) )\n                url = \"https://\" + url;\n\n            var psi = new ProcessStartInfo\n            {\n                FileName = url,\n                UseShellExecute = true\n            };\n            Process.Start( psi );\n            llb_Company.LinkVisited = true;\n        }\n\n        private void MT_About_Paint( object sender, PaintEventArgs e )\n        {\n            var entryAssembly = Assembly.GetEntryAssembly();\n\n            lb_AppName.Text = ( (AssemblyProductAttribute)Attribute.GetCustomAttribute(\n                entryAssembly,\n                typeof( AssemblyProductAttribute ),\n                false ) ).Product;\n            lb_Version.Text = ( (AssemblyInformationalVersionAttribute)Attribute.GetCustomAttribute(\n                entryAssembly,\n                typeof( AssemblyInformationalVersionAttribute ),\n                false ) ).InformationalVersion;\n            lb_Copyright.Text = ( (AssemblyCopyrightAttribute)Attribute.GetCustomAttribute(\n                entryAssembly,\n                typeof( AssemblyCopyrightAttribute ),\n                false ) ).Copyright;\n            llb_Company.Text = ( (AssemblyCompanyAttribute)Attribute.GetCustomAttribute(\n                entryAssembly,\n                typeof( AssemblyCompanyAttribute ),\n                false ) ).Company;\n\n            if ( lbox_Env.Items.Count == 0 )\n                lbox_Env.Items.Add( RuntimeInformation.FrameworkDescription );\n        }\n\n        private void openLogFolderToolStripMenuItem_Click( object sender, EventArgs e )\n        {\n            var logFolder = Path.Combine( ConfigManager.AppRootFolder, \"Logs\" );\n            if ( Directory.Exists( logFolder ) )\n            {\n                var startInfo = new ProcessStartInfo\n                {\n                    Arguments = logFolder,\n                    FileName = \"explorer.exe\"\n                };\n\n                Process.Start( startInfo );\n            }\n        }\n\n        private void closeThisWindowToolStripMenuItem_Click( object sender, EventArgs e )\n        {\n            Hide();\n        }\n\n        private void runAsAdministratorToolStripMenuItem_Click( object sender, EventArgs e )\n        {\n            User32.PostMessage( _mainWindowHandle, WinMsg.WM_HOTKEY, UserMessage.RunAsAdministrator, 0 );\n        }\n\n        private void aboutToolStripMenuItem_Click( object sender, EventArgs e )\n        {\n            mainTabs.SelectTab( 5 );\n        }\n\n        private void InitStorageConfig()\n        {\n            tb_configRoot.Text = ConfigManager.ConfigRootFolder;\n        }\n\n        private void btn_chooseConfigRoot_Click( object sender, EventArgs e )\n        {\n            using var fbd = new FolderBrowserDialog();\n\n            if ( fbd.ShowDialog() == DialogResult.OK && !string.IsNullOrWhiteSpace( fbd.SelectedPath ) )\n            {\n                tb_configRoot.Text = fbd.SelectedPath;\n                ConfigManager.SetConfigRoot( fbd.SelectedPath );\n            }\n        }\n\n        private void tsmiMainMenuRestart_Click( object sender, EventArgs e )\n        {\n            User32.PostMessage( _mainWindowHandle, WinMsg.WM_HOTKEY, UserMessage.RestartApp, 0 );\n        }\n\n        private void tsmiMainMenuQuit_Click( object sender, EventArgs e )\n        {\n            User32.PostMessage( _mainWindowHandle, WinMsg.WM_CLOSE, 0, 0 );\n        }\n    }\n}"
  },
  {
    "path": "WinForms/AppController/AppController.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFrameworks>net6.0-windows</TargetFrameworks>\n        <LangVersion>9</LangVersion>\n        <Nullable>enable</Nullable>\n        <UseWindowsForms>true</UseWindowsForms>\n    </PropertyGroup>\n\n    <ItemGroup>\n        <ProjectReference Include=\"..\\..\\Configuration\\Configuration.csproj\" />\n        <ProjectReference Include=\"..\\..\\Ipc\\IpcServer\\IpcServer.csproj\" />\n        <ProjectReference Include=\"..\\..\\VirtualDesktopWrapper\\VirtualDesktopWrapper.csproj\" />\n    </ItemGroup>\n\n    <ItemGroup>\n        <Compile Update=\"AppController.keyboard.cs\">\n            <SubType>Form</SubType>\n        </Compile>\n        <Compile Update=\"AppController.cs\">\n            <SubType>Form</SubType>\n        </Compile>\n        <Compile Update=\"AppController.logs.cs\">\n            <SubType>Form</SubType>\n        </Compile>\n        <Compile Update=\"AppController.rules.cs\">\n            <SubType>Form</SubType>\n        </Compile>\n        <Compile Update=\"RuleForm.cs\">\n            <SubType>Form</SubType>\n        </Compile>\n        <Compile Update=\"AppController.mouse.cs\">\n            <SubType>Form</SubType>\n        </Compile>\n        <Compile Update=\"AppController.ui.cs\">\n            <SubType>Form</SubType>\n        </Compile>\n        <Compile Update=\"AppController.cluster.cs\">\n            <SubType>Form</SubType>\n        </Compile>\n        <Compile Update=\"AppController.lang.cs\">\n            <SubType>Form</SubType>\n        </Compile>\n        <Compile Update=\"AppController.profile.cs\">\n          <SubType>Form</SubType>\n        </Compile>\n    </ItemGroup>\n\n    <PropertyGroup>\n        <SatelliteResourceLanguages>en-US,zh-Hans</SatelliteResourceLanguages>\n    </PropertyGroup>\n\n</Project>\n"
  },
  {
    "path": "WinForms/AppController/AppController.keyboard.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Windows.Forms;\nusing System.Windows.Input;\nusing VirtualSpace.Config;\nusing VirtualSpace.Helpers;\nusing VirtualSpace.VirtualDesktop.Api;\n\nnamespace VirtualSpace\n{\n    public partial class AppController\n    {\n        private void tv_keyboard_AfterSelect( object sender, TreeViewEventArgs e )\n        {\n            tb_hk_tip.Clear();\n\n            cb_hk_win.Checked = false;\n            cb_hk_ctrl.Checked = false;\n            cb_hk_alt.Checked = false;\n            cb_hk_shift.Checked = false;\n            cb_hk_key.SelectedIndex = -1;\n\n            tc_Keyboard.Visible = false;\n\n            var kbInConfig = Manager.Configs.KeyBindings;\n            var hotkeyId   = e.Node.Name;\n\n            if ( !kbInConfig.ContainsKey( hotkeyId ) )\n            {\n                var kb = Const.Hotkey.GetKeyBinding( hotkeyId );\n                if ( kb.MessageId == 0 ) return;\n                kbInConfig[hotkeyId] = kb;\n            }\n\n            lb_hk_func.Text = e.Node.FullPath;\n            lb_hk_extra.Text = Const.Hotkey.GetHotkeyExtra( hotkeyId );\n            tc_Keyboard.Visible = true;\n\n            if ( kbInConfig[hotkeyId].GhkCode == \"\" ) return;\n\n            var arr = kbInConfig[hotkeyId].GhkCode.Split( Const.Hotkey.SPLITTER );\n            if ( arr.Length == 5 )\n            {\n                cb_hk_win.Checked = arr[0] != Const.Hotkey.NONE;\n                cb_hk_ctrl.Checked = arr[1] != Const.Hotkey.NONE;\n                cb_hk_alt.Checked = arr[2] != Const.Hotkey.NONE;\n                cb_hk_shift.Checked = arr[3] != Const.Hotkey.NONE;\n\n                cb_hk_key.Text = arr[4];\n            }\n        }\n\n        private void btn_hk_RegAndSave_Click( object sender, EventArgs e )\n        {\n            tb_hk_tip.Clear();\n            if ( !Check() ) return;\n\n            var ghk = GetGhk();\n\n            RegHotkey( ghk );\n            SaveHotkey( ghk );\n        }\n\n        private void btn_hk_ClearAndSave_Click( object sender, EventArgs e )\n        {\n            tb_hk_tip.Clear();\n            var msgId = Const.Hotkey.GetKeyBinding( tv_keyboard.SelectedNode.Name ).MessageId;\n            GlobalHotKey.UnregisterHotKey( _mainWindowHandle, msgId );\n            ClearHotkey();\n            SaveHotkey( GetGhk() );\n        }\n\n        private bool Check()\n        {\n            if ( cb_hk_key.SelectedItem is not null ) return true;\n\n            tb_hk_tip.Text = Agent.Langs.GetString( \"KB.Hotkey.KeyCheck\" );\n            return false;\n        }\n\n        private (string keyCode, GlobalHotKey.KeyModifiers keyModifiers) GetGhk()\n        {\n            string ghkCode;\n            var    km = GlobalHotKey.KeyModifiers.None;\n\n            if ( cb_hk_key.SelectedIndex == 0 || cb_hk_key.SelectedItem is null )\n            {\n                ghkCode = \"\";\n            }\n            else\n            {\n                ghkCode = ( cb_hk_win.Checked ? Const.Hotkey.WIN : Const.Hotkey.NONE ) + Const.Hotkey.SPLITTER;\n                ghkCode += ( cb_hk_ctrl.Checked ? Const.Hotkey.CTRL : Const.Hotkey.NONE ) + Const.Hotkey.SPLITTER;\n                ghkCode += ( cb_hk_alt.Checked ? Const.Hotkey.ALT : Const.Hotkey.NONE ) + Const.Hotkey.SPLITTER;\n                ghkCode += ( cb_hk_shift.Checked ? Const.Hotkey.SHIFT : Const.Hotkey.NONE ) + Const.Hotkey.SPLITTER;\n\n                km = cb_hk_win.Checked ? GlobalHotKey.KeyModifiers.WindowsKey : GlobalHotKey.KeyModifiers.None;\n                km |= cb_hk_ctrl.Checked ? GlobalHotKey.KeyModifiers.Ctrl : GlobalHotKey.KeyModifiers.None;\n                km |= cb_hk_alt.Checked ? GlobalHotKey.KeyModifiers.Alt : GlobalHotKey.KeyModifiers.None;\n                km |= cb_hk_shift.Checked ? GlobalHotKey.KeyModifiers.Shift : GlobalHotKey.KeyModifiers.None;\n\n                ghkCode += cb_hk_key.SelectedItem.ToString();\n            }\n\n            return new ValueTuple<string, GlobalHotKey.KeyModifiers>( ghkCode, km );\n        }\n\n        private void SaveHotkey( (string keyCode, GlobalHotKey.KeyModifiers keyModifiers) ghk )\n        {\n            var hotkeyId = tv_keyboard.SelectedNode.Name;\n            var kb       = Const.Hotkey.GetKeyBinding( hotkeyId );\n            kb.GhkCode = ghk.keyCode;\n            Manager.Configs.KeyBindings[hotkeyId] = kb;\n            Manager.Save( reason: kb.GhkCode.Replace( Const.Hotkey.NONE + Const.Hotkey.SPLITTER, \"\" ), reasonName: hotkeyId );\n            tb_hk_tip.Text += Agent.Langs.GetString( \"KB.Hotkey.SettingsSaved\" ) + Const.WindowsCRLF;\n        }\n\n        private void RegHotkey( (string keyCode, GlobalHotKey.KeyModifiers keyModifiers) ghk )\n        {\n            var hotkeyId = tv_keyboard.SelectedNode.Name;\n            var msgId    = Const.Hotkey.GetKeyBinding( hotkeyId ).MessageId;\n            GlobalHotKey.UnregisterHotKey( _mainWindowHandle, msgId );\n\n            if ( cb_hk_key.SelectedIndex == 0 )\n            {\n                ClearHotkey();\n                return;\n            }\n\n            if ( GlobalHotKey.RegHotKey( _mainWindowHandle,\n                    msgId,\n                    ghk.keyModifiers,\n                    KeyInterop.VirtualKeyFromKey( Enum.Parse<Key>( cb_hk_key.SelectedItem.ToString() ) ) ) )\n            {\n                tb_hk_tip.Text += Agent.Langs.GetString( \"KB.Hotkey.Reg.Success\" ) + Const.WindowsCRLF;\n            }\n            else\n            {\n                tb_hk_tip.Text += Agent.Langs.GetString( \"KB.Hotkey.Reg.Fail\" ) + Const.WindowsCRLF;\n            }\n        }\n\n        private void ClearHotkey()\n        {\n            cb_hk_win.Checked = false;\n            cb_hk_ctrl.Checked = false;\n            cb_hk_alt.Checked = false;\n            cb_hk_shift.Checked = false;\n            cb_hk_key.SelectedIndex = -1;\n            tb_hk_tip.Text += Agent.Langs.GetString( \"KB.Hotkey.Cleared\" ) + Const.WindowsCRLF;\n        }\n\n        private void cb_hk_key_SelectedIndexChanged( object sender, EventArgs e )\n        {\n            tb_hk_tip.Clear();\n        }\n\n        private void cb_hk_win_CheckedChanged( object sender, EventArgs e )\n        {\n            tb_hk_tip.Clear();\n        }\n\n        private void cb_hk_ctrl_CheckedChanged( object sender, EventArgs e )\n        {\n            tb_hk_tip.Clear();\n        }\n\n        private void cb_hk_alt_CheckedChanged( object sender, EventArgs e )\n        {\n            tb_hk_tip.Clear();\n        }\n\n        private void cb_hk_shift_CheckedChanged( object sender, EventArgs e )\n        {\n            tb_hk_tip.Clear();\n        }\n\n        private void InitKeyboardNodes()\n        {\n            var nodeSvd = tv_keyboard.Nodes[\"hk_root_desktop\"].Nodes[\"hk_parent_svd\"];\n            var nodeMw  = tv_keyboard.Nodes[\"hk_root_window\"].Nodes[\"hk_parent_win_move\"];\n            var nodeMwf = tv_keyboard.Nodes[\"hk_root_window\"].Nodes[\"hk_parent_win_move_follow\"];\n            nodeSvd.Nodes.Clear();\n            nodeMw.Nodes.Clear();\n            nodeMwf.Nodes.Clear();\n\n            for ( var i = 1; i <= DesktopWrapper.Count; i++ )\n            {\n                nodeSvd.Nodes.Add( Const.Hotkey.SVD_TREE_NODE_PREFIX + i, Agent.Langs.GetString( \"KB.Hotkey.SVD\" ) + i );\n                nodeMw.Nodes.Add( Const.Hotkey.MW_TREE_NODE_PREFIX + i, Agent.Langs.GetString( \"KB.Hotkey.MW\" ) + i );\n                nodeMwf.Nodes.Add( Const.Hotkey.MWF_TREE_NODE_PREFIX + i, Agent.Langs.GetString( \"KB.Hotkey.MWF\" ) + i );\n            }\n\n            nodeSvd.Nodes.Add( Const.Hotkey.SWITCH_BACK_LAST, Agent.Langs.GetString( \"KB.Hotkey.SVD_BACK_LAST\" ) );\n\n            tc_Keyboard.Visible = false;\n            tv_keyboard.ExpandAll();\n        }\n    }\n}"
  },
  {
    "path": "WinForms/AppController/AppController.lang.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Globalization;\nusing System.Windows.Forms;\nusing VirtualSpace.AppLogs;\nusing VirtualSpace.Helpers;\nusing ConfigManager = VirtualSpace.Config.Manager;\n\nnamespace VirtualSpace\n{\n    public partial class AppController\n    {\n        private static void SetAllLang( string lang )\n        {\n            CultureInfo.CurrentCulture = new CultureInfo( lang );\n            CultureInfo.CurrentUICulture = new CultureInfo( lang );\n\n            Logger.Info( \"Change Language: \" + CultureInfo.CurrentUICulture.DisplayName );\n\n            void Invoker()\n            {\n                SetControlLang( _instance.logCMS, lang );\n\n                _instance.tv_keyboard.Nodes.Clear();\n                _instance.tv_keyboard.Nodes.AddRange( new[]\n                {\n                    (TreeNode)Resources.GetObject( \"tv_keyboard.Nodes\" ),\n                    (TreeNode)Resources.GetObject( \"tv_keyboard.Nodes1\" ),\n                    (TreeNode)Resources.GetObject( \"tv_keyboard.Nodes2\" )\n                } );\n                _instance.InitKeyboardNodes();\n\n                _instance.tv_mouse.Nodes.Clear();\n                _instance.tv_mouse.Nodes.AddRange( new[]\n                {\n                    (TreeNode)Resources.GetObject( \"tv_mouse.Nodes\" )\n                } );\n                _instance.InitMouseNodes();\n\n                SetControlLang( _instance, lang );\n            }\n\n            if ( _instance.InvokeRequired )\n            {\n                _instance.Invoke( (MethodInvoker)Invoker );\n            }\n            else\n            {\n                Invoker();\n            }\n        }\n\n        private static void SetControlLang( Control control, string lang )\n        {\n            var ci = new CultureInfo( lang );\n\n            switch ( control )\n            {\n                case MenuStrip strip:\n                {\n                    Resources.ApplyResources( control, strip.Name, ci );\n                    foreach ( var item in strip.Items )\n                    {\n                        if ( item is ToolStripMenuItem c )\n                            SetMenuItemLang( c, lang );\n                    }\n\n                    break;\n                }\n                case ContextMenuStrip ms:\n                {\n                    Resources.ApplyResources( control, ms.Name, ci );\n                    foreach ( var item in ms.Items )\n                    {\n                        if ( item is ToolStripMenuItem c )\n                            SetMenuItemLang( c, lang );\n                    }\n\n                    break;\n                }\n                case ListView lv:\n                {\n                    foreach ( var item in lv.Columns )\n                    {\n                        if ( item is ColumnHeader ch )\n                            Resources.ApplyResources( ch, ch.Name, ci );\n                    }\n\n                    break;\n                }\n                case ToolStrip ts:\n                {\n                    foreach ( var item in ts.Items )\n                    {\n                        switch ( item )\n                        {\n                            case ToolStripButton tsb:\n                                SetToolStripButtonLang( tsb, lang );\n                                break;\n                            case ToolStripSplitButton tssb:\n                                Resources.ApplyResources( tssb, tssb.Name, ci );\n                                foreach ( var m in tssb.DropDownItems )\n                                {\n                                    SetMenuItemLang( m as ToolStripMenuItem, lang );\n                                }\n\n                                break;\n                        }\n                    }\n\n                    break;\n                }\n            }\n\n            foreach ( var item in control.Controls )\n            {\n                if ( item is Control c )\n                {\n                    Resources.ApplyResources( c, c.Name, ci );\n                    SetControlLang( c, lang );\n                }\n            }\n        }\n\n        private static void SetMenuItemLang( ToolStripMenuItem item, string lang )\n        {\n            var ci = new CultureInfo( lang );\n            Resources.ApplyResources( item, item.Name, ci );\n            if ( item.DropDownItems.Count > 0 )\n            {\n                foreach ( ToolStripItem c in item.DropDownItems )\n                {\n                    if ( c is ToolStripMenuItem menuItem )\n                    {\n                        SetMenuItemLang( menuItem, lang );\n                    }\n                }\n            }\n        }\n\n        private static void SetToolStripButtonLang( ToolStripButton item, string lang )\n        {\n            var ci = new CultureInfo( lang );\n            Resources.ApplyResources( item, item.Name, ci );\n        }\n\n        private void optionsToolStripMenuItem_DropDownOpening( object sender, EventArgs e )\n        {\n            void UpdateCheckState( object? obj, EventArgs evt )\n            {\n                var l = (ToolStripMenuItem)obj;\n\n                ConfigManager.CurrentProfile.UI.Language = l.Name;\n                ConfigManager.Save( reason: ConfigManager.CurrentProfile.UI.Language );\n                User32.PostMessage( _instance._mainWindowHandle, WinMsg.WM_HOTKEY, UserMessage.UpdateTrayLang, 0 );\n\n                if ( Math.Abs( SysInfo.Dpi.ScaleX - 1.0f ) > 0 )\n                {\n                    _cancelTokenSourceForLog.Cancel();\n                    User32.PostMessage( _mainWindowHandle, WinMsg.WM_HOTKEY, UserMessage.RestartAppController, 0 );\n                    return;\n                }\n\n                SetAllLang( l.Name );\n\n                foreach ( ToolStripMenuItem lang in langToolStripMenuItem.DropDownItems )\n                {\n                    lang.Checked = lang.Name == l.Name;\n                }\n\n                ReadNavConfig();\n            }\n\n            langToolStripMenuItem.DropDownItems.Clear();\n            foreach ( var (key, value) in Agent.ValidLangs )\n            {\n                var langItem = new ToolStripMenuItem\n                {\n                    Checked = CultureInfo.CurrentUICulture.Name == key,\n                    Name = key,\n                    Text = value\n                };\n                langItem.Click += UpdateCheckState;\n                langToolStripMenuItem.DropDownItems.Add( langItem );\n            }\n        }\n    }\n}"
  },
  {
    "path": "WinForms/AppController/AppController.logs.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Drawing;\nusing System.Threading;\nusing System.Threading.Channels;\nusing System.Windows.Forms;\nusing VirtualSpace.AppLogs;\nusing ConfigManager = VirtualSpace.Config.Manager;\n\nnamespace VirtualSpace\n{\n    public partial class AppController\n    {\n        private static readonly Channel<LogMessage>     LogChannel               = Logger.LogChannel;\n        private readonly        CancellationTokenSource _cancelTokenSourceForLog = new();\n        private                 Point                   _logTabCursorPos;\n\n        private async void PickLogAndWrite( CancellationToken stoppingToken )\n        {\n            showLogsInGuiToolStripMenuItem.Checked = ConfigManager.Configs.LogConfig.ShowLogsInGui;\n            showLogsInGuiToolStripMenuItem.CheckedChanged += showLogsInGuiToolStripMenuItem_CheckedChanged;\n\n            try\n            {\n                while ( await LogChannel.Reader.WaitToReadAsync( stoppingToken ) )\n                {\n                    if ( LogChannel.Reader.TryRead( out var message ) )\n                    {\n                        switch ( message.Type )\n                        {\n                            case \"VERBOSE\":\n                                AppendLog( tbVerbose, message );\n                                break;\n                            case \"DEBUG\":\n                                AppendLog( tbDebug, message );\n                                break;\n                            case \"EVENT\":\n                                AppendLog( tbEvent, message );\n                                break;\n                            case \"INFO\":\n                                AppendLog( tbInfo, message );\n                                break;\n                            case \"WARNING\":\n                                AppendLog( tbWarning, message );\n                                break;\n                            case \"ERROR\":\n                                AppendLog( tbError, message );\n                                break;\n                            default:\n                                AppendLog( tbError, message );\n                                break;\n                        }\n                    }\n                }\n            }\n            catch\n            {\n                // ignored\n            }\n            finally\n            {\n                _cancelTokenSourceForLog.Dispose();\n            }\n        }\n\n        private void AppendLog( TextBox tb, LogMessage message )\n        {\n            tb.AppendText( message.Message );\n        }\n\n        private void logTabs_Click( object sender, EventArgs e )\n        {\n            var e2 = (MouseEventArgs)e;\n            if ( e2.Button == MouseButtons.Right )\n            {\n                _logTabCursorPos = Cursor.Position;\n                logCMS.Show( logTabs, e2.Location );\n            }\n        }\n\n        private void clearToolStripMenuItem_Click( object sender, EventArgs e )\n        {\n            var cnt = logTabs.TabCount;\n            for ( var i = 0; i < cnt; i++ )\n            {\n                var rect = logTabs.GetTabRect( i );\n                if ( rect.Contains( logTabs.PointToClient( _logTabCursorPos ) ) )\n                {\n                    var dialogResult = MessageBox.Show(\n                        $@\"Do you want to clear [{logTabs.TabPages[i].Text}] logs?\",\n                        @\"Confirm\",\n                        MessageBoxButtons.YesNo );\n                    switch ( dialogResult )\n                    {\n                        case DialogResult.Yes:\n                            var tb = logTabs.TabPages[i].Controls[0] as TextBox;\n                            tb.Clear();\n                            break;\n                        case DialogResult.No:\n                            break;\n                    }\n\n                    break;\n                }\n            }\n        }\n\n        private void showLogsInGuiToolStripMenuItem_CheckedChanged( object? sender, EventArgs e )\n        {\n            var item = sender as ToolStripMenuItem;\n            Logger.ShowLogsInGui = item.Checked;\n            ConfigManager.Configs.LogConfig.ShowLogsInGui = item.Checked;\n            ConfigManager.Save( reason: ConfigManager.Configs.LogConfig.ShowLogsInGui );\n        }\n    }\n}"
  },
  {
    "path": "WinForms/AppController/AppController.mouse.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Collections.Generic;\nusing System.Windows.Forms;\nusing VirtualSpace.Config;\nusing VirtualSpace.Helpers;\n\nnamespace VirtualSpace\n{\n    public partial class AppController\n    {\n        private void InitMouseConfig()\n        {\n            chb_MouseOnTaskbarSwitchDesktop.Checked = Manager.CurrentProfile.Mouse.UseWheelSwitchDesktopWhenOnTaskbar;\n            chb_MouseOnTaskbarSwitchDesktop.CheckedChanged += chb_MouseOnTaskbarSwitchDesktop_CheckedChanged;\n        }\n\n        private void chb_MouseOnTaskbarSwitchDesktop_CheckedChanged( object? sender, EventArgs e )\n        {\n            Manager.CurrentProfile.Mouse.UseWheelSwitchDesktopWhenOnTaskbar = chb_MouseOnTaskbarSwitchDesktop.Checked;\n            var msg = Manager.CurrentProfile.Mouse.UseWheelSwitchDesktopWhenOnTaskbar ? UserMessage.EnableMouseHook : UserMessage.DisableMouseHook;\n            User32.PostMessage( _mainWindowHandle, WinMsg.WM_HOTKEY, (ulong)msg, 0 );\n            Manager.Save( reason: Manager.CurrentProfile.Mouse.UseWheelSwitchDesktopWhenOnTaskbar );\n        }\n\n        private void tv_mouse_AfterSelect( object sender, TreeViewEventArgs e )\n        {\n            tc_Mouse.Visible = false;\n\n            var ma            = Manager.Configs.MouseAction;\n            var mouseActionId = e.Node.Name;\n            if ( !ma.ContainsKey( mouseActionId ) )\n            {\n                if ( MouseAction.Info.ContainsKey( mouseActionId ) )\n                {\n                    ma[mouseActionId] = MouseAction.Info[mouseActionId];\n                }\n                else\n                {\n                    return;\n                }\n            }\n\n            lb_mouse_action.Text = e.Node.FullPath;\n            tc_Mouse.Visible = true;\n\n            if ( mouseActionId.StartsWith( MouseAction.MOUSE_NODE_DESKTOP_PREFIX ) )\n            {\n                var items = new List<object>\n                {\n                    new {Value = MouseAction.Action.DesktopVisibleAndCloseView, Text = Agent.Langs.GetString( \"Mouse.Action.DesktopVisibleAndCloseView\" )},\n                    new {Value = MouseAction.Action.DesktopVisibleOnly, Text = Agent.Langs.GetString( \"Mouse.Action.DesktopVisibleOnly\" )},\n                    new {Value = MouseAction.Action.ContextMenu, Text = Agent.Langs.GetString( \"Mouse.Action.ContextMenu\" )},\n                    new {Value = MouseAction.Action.DesktopShowForSelectedDesktop, Text = Agent.Langs.GetString( \"Mouse.Action.DesktopShowForSelectedDesktop\" )},\n                    new {Value = MouseAction.Action.DoNothing, Text = Agent.Langs.GetString( \"Mouse.Action.DoNothing\" )}\n                };\n                WinForms.SetComboBoxDataSource( cb_mouse_func, items );\n            }\n            else if ( mouseActionId.StartsWith( MouseAction.MOUSE_NODE_WINDOW_PREFIX ) )\n            {\n                var items = new List<object>\n                {\n                    new\n                    {\n                        Value = MouseAction.Action.WindowActiveDesktopVisibleAndCloseView,\n                        Text = Agent.Langs.GetString( \"Mouse.Action.WindowActiveDesktopVisibleAndCloseView\" )\n                    },\n                    new\n                    {\n                        Value = MouseAction.Action.WindowActiveDesktopVisibleOnly,\n                        Text = Agent.Langs.GetString( \"Mouse.Action.WindowActiveDesktopVisibleOnly\" )\n                    },\n                    new {Value = MouseAction.Action.ContextMenu, Text = Agent.Langs.GetString( \"Mouse.Action.ContextMenu\" )},\n                    new {Value = MouseAction.Action.WindowHideFromView, Text = Agent.Langs.GetString( \"VDW.CTM.Window.HideFromView\" )},\n                    new {Value = MouseAction.Action.WindowClose, Text = Agent.Langs.GetString( \"Mouse.Action.WindowClose\" )},\n                    new {Value = MouseAction.Action.WindowShowForSelectedProcessOnly, Text = Agent.Langs.GetString( \"Mouse.Action.WindowShowForSelectedProcessOnly\" )},\n                    new\n                    {\n                        Value = MouseAction.Action.WindowShowForSelectedProcessInSelectedDesktop,\n                        Text = Agent.Langs.GetString( \"Mouse.Action.WindowShowForSelectedProcessInSelectedDesktop\" )\n                    },\n                    new {Value = MouseAction.Action.DoNothing, Text = Agent.Langs.GetString( \"Mouse.Action.DoNothing\" )}\n                };\n                WinForms.SetComboBoxDataSource( cb_mouse_func, items );\n            }\n\n            cb_mouse_func.SelectedValue = ma[mouseActionId];\n        }\n\n        private void btn_mouse_save_Click( object sender, EventArgs e )\n        {\n            var maId = tv_mouse.SelectedNode.Name;\n            Manager.Configs.MouseAction[maId] = (MouseAction.Action)cb_mouse_func.SelectedValue;\n            Manager.Save( reason: Manager.Configs.MouseAction[maId], reasonName: maId );\n        }\n\n        private void InitMouseNodes()\n        {\n            var nodeDesktop = tv_mouse.Nodes[\"mouse_root_mainview\"].Nodes[\"mouse_parent_desktop\"];\n            var nodeWindow  = tv_mouse.Nodes[\"mouse_root_mainview\"].Nodes[\"mouse_parent_window\"];\n            nodeDesktop.Nodes.Clear();\n            nodeWindow.Nodes.Clear();\n\n            string GetLocaleText( string text )\n            {\n                text = text\n                    .Replace( \"Left\", Agent.Langs.GetString( \"Keys.Left\" ) )\n                    .Replace( \"Middle\", Agent.Langs.GetString( \"Keys.Middle\" ) )\n                    .Replace( \"Right\", Agent.Langs.GetString( \"Keys.Right\" ) );\n                return text;\n            }\n\n            foreach ( var kv in MouseAction.Info1 )\n            {\n                if ( kv.Key.StartsWith( MouseAction.MOUSE_NODE_DESKTOP_PREFIX ) )\n                {\n                    nodeDesktop.Nodes.Add( kv.Key, GetLocaleText( kv.Key.Replace( MouseAction.MOUSE_NODE_DESKTOP_PREFIX, \"\" ) ) );\n                }\n                else if ( kv.Key.StartsWith( MouseAction.MOUSE_NODE_WINDOW_PREFIX ) )\n                {\n                    nodeWindow.Nodes.Add( kv.Key, GetLocaleText( kv.Key.Replace( MouseAction.MOUSE_NODE_WINDOW_PREFIX, \"\" ) ) );\n                }\n            }\n\n            tc_Mouse.Visible = false;\n            tv_mouse.ExpandAll();\n        }\n    }\n}"
  },
  {
    "path": "WinForms/AppController/AppController.nav.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing ConfigManager = VirtualSpace.Config.Manager;\n\nnamespace VirtualSpace\n{\n    public partial class AppController\n    {\n        private void ReadNavConfig( bool resetEventHandlers = true )\n        {\n            if ( resetEventHandlers )\n            {\n                cb_nav_circle_h.CheckedChanged -= cb_nav_circle_h_CheckedChanged;\n                cb_nav_circle_h_type.SelectedIndexChanged -= cb_nav_circle_h_type_SelectedIndexChanged;\n                cb_nav_circle_v.CheckedChanged -= cb_nav_circle_v_CheckedChanged;\n            }\n\n            cb_nav_circle_h_type.Items.Clear();\n            cb_nav_circle_h_type.Items.Add( Agent.Langs.GetString( \"Nav.CircleHType.NextRow\" ) );\n            cb_nav_circle_h_type.Items.Add( Agent.Langs.GetString( \"Nav.CircleHType.SameRow\" ) );\n\n            cb_nav_circle_h.Checked = ConfigManager.CurrentProfile.Navigation.CirculationH;\n            cb_nav_circle_h_type.SelectedIndex = ConfigManager.CurrentProfile.Navigation.CirculationHType;\n            cb_nav_circle_v.Checked = ConfigManager.CurrentProfile.Navigation.CirculationV;\n\n            if ( resetEventHandlers )\n            {\n                cb_nav_circle_h.CheckedChanged += cb_nav_circle_h_CheckedChanged;\n                cb_nav_circle_h_type.SelectedIndexChanged += cb_nav_circle_h_type_SelectedIndexChanged;\n                cb_nav_circle_v.CheckedChanged += cb_nav_circle_v_CheckedChanged;\n            }\n        }\n\n        private void cb_nav_circle_h_CheckedChanged( object? sender, EventArgs e )\n        {\n            ConfigManager.CurrentProfile.Navigation.CirculationH = cb_nav_circle_h.Checked;\n            ConfigManager.Save( reason: ConfigManager.CurrentProfile.Navigation.CirculationH );\n        }\n\n        private void cb_nav_circle_v_CheckedChanged( object? sender, EventArgs e )\n        {\n            ConfigManager.CurrentProfile.Navigation.CirculationV = cb_nav_circle_v.Checked;\n            ConfigManager.Save( reason: ConfigManager.CurrentProfile.Navigation.CirculationV );\n        }\n\n        private void cb_nav_circle_h_type_SelectedIndexChanged( object? sender, EventArgs e )\n        {\n            ConfigManager.CurrentProfile.Navigation.CirculationHType = cb_nav_circle_h_type.SelectedIndex;\n            ConfigManager.Save( reason: ConfigManager.CurrentProfile.Navigation.CirculationHType );\n        }\n    }\n}"
  },
  {
    "path": "WinForms/AppController/AppController.plugins.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Collections.Generic;\nusing System.Windows.Forms;\nusing VirtualSpace.Plugin;\n\nnamespace VirtualSpace\n{\n    public partial class AppController\n    {\n        private static readonly List<PluginInfo> PluginInfos = PluginHost.Plugins;\n\n        private void InitPluginListView()\n        {\n            ///////////////////////////////////////\n            // fix no ColumnHeader name issue\n            lvc_PluginName.Name = nameof( lvc_PluginName );\n            lvc_PluginVersion.Name = nameof( lvc_PluginVersion );\n            lvc_PluginAuthor.Name = nameof( lvc_PluginAuthor );\n            lvc_PluginEmail.Name = nameof( lvc_PluginEmail );\n        }\n\n        private void mainTabs_SelectedIndexChanged( object sender, EventArgs e )\n        {\n            var s = sender as TabControl;\n            if ( s?.SelectedTab != MT_Plugins ) return;\n\n            lv_Plugins.ItemCheck -= lv_Plugins_ItemCheck;\n\n            lv_Plugins.Items.Clear();\n            foreach ( var pluginInfo in PluginInfos )\n            {\n                lv_Plugins.Items.Add( LviByPlugin( pluginInfo ) );\n            }\n\n            lv_Plugins.ItemCheck += lv_Plugins_ItemCheck;\n        }\n\n        private static ListViewItem LviByPlugin( PluginInfo plugin )\n        {\n            var item = new ListViewItem( plugin.Display );\n            item.SubItems.Add( plugin.Version );\n            item.SubItems.Add( plugin.Author );\n            item.SubItems.Add( plugin.Email );\n            item.Checked = plugin.AutoStart;\n            return item;\n        }\n\n        private void lv_Plugins_SelectedIndexChanged( object sender, EventArgs e )\n        {\n            if ( lv_Plugins.SelectedItems.Count > 0 )\n            {\n                btn_PluginSettings.Enabled = true;\n            }\n            else\n            {\n                btn_PluginSettings.Enabled = false;\n            }\n        }\n\n        private void btn_PluginSettings_Click( object sender, EventArgs e )\n        {\n            if ( lv_Plugins.SelectedItems.Count <= 0 ) return;\n            var p = PluginInfos[lv_Plugins.SelectedIndices[0]];\n            PluginHost.PluginSettings( p );\n        }\n\n        private void lv_Plugins_ItemCheck( object? sender, ItemCheckEventArgs e )\n        {\n            var selectedIndex = e.Index;\n            if ( e.NewValue == CheckState.Checked )\n            {\n                PluginInfos[selectedIndex].AutoStart = true;\n                PluginHost.StartPlugin( PluginInfos[selectedIndex] );\n            }\n            else\n            {\n                PluginInfos[selectedIndex].AutoStart = false;\n                PluginHost.ClosePlugin( PluginInfos[selectedIndex] );\n            }\n\n            PluginManager.SavePluginInfo( PluginInfos[selectedIndex] );\n        }\n    }\n}"
  },
  {
    "path": "WinForms/AppController/AppController.profile.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing System.IO;\nusing System.Linq;\nusing System.Windows.Forms;\nusing VirtualSpace.Config.Events.Expression;\nusing ConfigManager = VirtualSpace.Config.Manager;\n\nnamespace VirtualSpace\n{\n    public partial class AppController\n    {\n        private string _editProfileName = string.Empty;\n\n        private void InitProfileList()\n        {\n            cbb_profiles.Items.Clear();\n            AddToComboBox( ConfigManager.Configs.Profiles.Keys.ToArray(), ConfigManager.Configs.CurrentProfileName );\n            cbb_profiles.KeyDown += cbb_profilesOnKeyDown;\n            cbb_profiles.KeyUp += cbb_profilesOnKeyUp;\n            cbb_profiles.LostFocus += cbb_profilesOnLostFocus;\n        }\n\n        private void AddToComboBox( string[] profileNames, string profileName )\n        {\n            cbb_profiles.SelectedIndexChanged -= cbb_profilesOnSelectedIndexChanged;\n            cbb_profiles.Items.AddRange( profileNames );\n            cbb_profiles.SelectedItem = profileName;\n            cbb_profiles.SelectedIndexChanged += cbb_profilesOnSelectedIndexChanged;\n        }\n\n        private void cbb_profilesOnKeyDown( object? sender, KeyEventArgs e )\n        {\n            switch ( e.KeyCode )\n            {\n                case Keys.Down or Keys.Up or Keys.Enter or Keys.Return:\n                    if ( cbb_profiles.DropDownStyle == ComboBoxStyle.Simple )\n                    {\n                        e.Handled = true;\n                    }\n\n                    break;\n            }\n        }\n\n        private void cbb_profilesOnKeyUp( object? sender, KeyEventArgs e )\n        {\n            if ( e.KeyCode is not (Keys.Enter or Keys.Return) ) return;\n            NameProfile();\n            e.Handled = true;\n        }\n\n        private void cbb_profilesOnLostFocus( object? sender, EventArgs e )\n        {\n            if ( cbb_profiles.DropDownStyle == ComboBoxStyle.Simple )\n            {\n                cbb_profiles.DropDownStyle = ComboBoxStyle.DropDownList;\n                cbb_profiles.SelectedItem = _editProfileName;\n            }\n        }\n\n        private void NameProfile()\n        {\n            if ( _editProfileName == string.Empty || _editProfileName == cbb_profiles.Text )\n            {\n                goto RESET;\n            }\n\n            var newProfileName = cbb_profiles.Text;\n            var isValid = !string.IsNullOrEmpty( newProfileName ) &&\n                          newProfileName.IndexOfAny( Path.GetInvalidFileNameChars() ) < 0 &&\n                          !File.Exists( Path.Combine( ConfigManager.ProfileFolder, newProfileName ) );\n\n            if ( ConfigManager.Configs.Profiles.ContainsKey( newProfileName ) || !isValid )\n            {\n                MessageBox.Show( Agent.Langs.GetString( \"Profile.Warning.InvalidProfileName\" ),\n                    Agent.Langs.GetString( \"MsgBox.Caption.Warning\" ),\n                    MessageBoxButtons.OK,\n                    MessageBoxIcon.Warning );\n                goto RESET;\n            }\n\n            var index = cbb_profiles.Items.IndexOf( _editProfileName );\n            RemoveProfile( _editProfileName );\n            CreateProfile( cbb_profiles.Text );\n            cbb_profiles.Items[index] = cbb_profiles.Text;\n            cbb_profiles.SelectedItem = newProfileName;\n\n            RESET:\n\n            cbb_profiles.DropDownStyle = ComboBoxStyle.DropDownList;\n            _editProfileName = string.Empty;\n        }\n\n        private void cbb_profilesOnSelectedIndexChanged( object? sender, EventArgs e )\n        {\n            if ( cbb_profiles.DropDownStyle == ComboBoxStyle.Simple && cbb_profiles.Items.Contains( cbb_profiles.Text ) ) return;\n\n            var selectedProfile = cbb_profiles.SelectedItem.ToString();\n            if ( selectedProfile == ConfigManager.Configs.CurrentProfileName ) return;\n            SwitchProfile( selectedProfile );\n            // User32.PostMessage( _mainWindowHandle, WinMsg.WM_HOTKEY, UserMessage.RestartAppController, 0 );\n        }\n\n        private void btn_profile_dup_Click( object sender, EventArgs e )\n        {\n            var newProfileName = cbb_profiles.Text + \" (copy)\";\n\n            var isValid = !string.IsNullOrEmpty( newProfileName ) &&\n                          newProfileName.IndexOfAny( Path.GetInvalidFileNameChars() ) < 0 &&\n                          !File.Exists( Path.Combine( ConfigManager.ProfileFolder, newProfileName ) );\n\n            if ( ConfigManager.Configs.Profiles.ContainsKey( newProfileName ) || !isValid )\n            {\n                MessageBox.Show( Agent.Langs.GetString( \"Profile.Warning.InvalidProfileName\" ),\n                    Agent.Langs.GetString( \"MsgBox.Caption.Warning\" ),\n                    MessageBoxButtons.OK,\n                    MessageBoxIcon.Warning );\n                return;\n            }\n\n            CreateProfile( newProfileName );\n            AddToComboBox( new[] {newProfileName}, newProfileName );\n        }\n\n        private void btn_profile_del_Click( object sender, EventArgs e )\n        {\n            if ( ConfigManager.Configs.Profiles.Count == 1 )\n            {\n                MessageBox.Show( Agent.Langs.GetString( \"Profile.Warning.LastProfileProtect\" ),\n                    Agent.Langs.GetString( \"MsgBox.Caption.Warning\" ),\n                    MessageBoxButtons.OK,\n                    MessageBoxIcon.Warning );\n                return;\n            }\n\n            if ( MessageBox.Show( Agent.Langs.GetString( \"Profile.Confirm.Delete\" ),\n                    Agent.Langs.GetString( \"MsgBox.Caption.Confirm\" ),\n                    MessageBoxButtons.YesNo,\n                    MessageBoxIcon.Warning ) != DialogResult.Yes ) return;\n\n            var delProfile = cbb_profiles.Text;\n            RemoveProfile( delProfile );\n\n            cbb_profiles.Items.Remove( delProfile );\n            cbb_profiles.SelectedItem = ConfigManager.Configs.CurrentProfileName;\n\n            SwitchProfile( ConfigManager.Configs.CurrentProfileName );\n        }\n\n        private void btn_profile_rename_Click( object sender, EventArgs e )\n        {\n            if ( ConfigManager.Configs.Profiles.Count == 1 )\n            {\n                MessageBox.Show( Agent.Langs.GetString( \"Profile.Warning.LastProfileProtect\" ),\n                    Agent.Langs.GetString( \"MsgBox.Caption.Warning\" ),\n                    MessageBoxButtons.OK,\n                    MessageBoxIcon.Warning );\n                return;\n            }\n\n            cbb_profiles.DropDownStyle = ComboBoxStyle.Simple;\n            cbb_profiles.Focus();\n            _editProfileName = cbb_profiles.Text;\n        }\n\n        private void RemoveProfile( string delProfile )\n        {\n            ConfigManager.Configs.Profiles.Remove( delProfile );\n            ConfigManager.Configs.CurrentProfileName = ConfigManager.Configs.Profiles.Keys.Last();\n            ConfigManager.Save( reason: \"Delete\", reasonName: \"Profile\" );\n            ConfigManager.DeleteFilesOfProfile( delProfile );\n        }\n\n        private void CreateProfile( string profileName )\n        {\n            var newProfile = ConfigManager.CurrentProfile.Clone();\n            ConfigManager.Configs.Profiles.Add( profileName, newProfile );\n            ConfigManager.Configs.CurrentProfileName = profileName;\n            ConfigManager.Save( reason: \"Create\", reasonName: \"Profile\" );\n\n            ConfigManager.SaveCluster( ConfigManager.Configs.Cluster ); // save cluster for new profile\n            Conditions.SaveRules( Conditions.FetchRules() ); // save rules for new profile\n\n            ReadRules();\n        }\n\n        private void SwitchProfile( string name )\n        {\n            ConfigManager.SwitchProfile( name );\n\n            InitClusterConfig( false );\n            InitUiConfig( false );\n            ReadNavConfig( false );\n            ReadRules();\n        }\n    }\n}"
  },
  {
    "path": "WinForms/AppController/AppController.resx",
    "content": "﻿<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <assembly alias=\"mscorlib\" name=\"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\" />\n  <data name=\"logTabVerbose.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>5</value>\n  </data>\n  <data name=\"&gt;&gt;chb_showVDIndexOnTrayIcon.ZOrder\" xml:space=\"preserve\">\n    <value>4</value>\n  </data>\n  <assembly alias=\"System.Windows.Forms\" name=\"System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\" />\n  <data name=\"btn_mouse_save.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <assembly alias=\"System.Drawing\" name=\"System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\" />\n  <data name=\"tbVerbose.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1145, 663</value>\n  </data>\n  <data name=\"btn_hk_RegAndSave.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>12, 80</value>\n  </data>\n  <data name=\"&gt;&gt;cb_RuleProfiles.Name\" xml:space=\"preserve\">\n    <value>cb_RuleProfiles</value>\n  </data>\n  <data name=\"cb_hk_key.Items10\" xml:space=\"preserve\">\n    <value>D0</value>\n  </data>\n  <data name=\"&gt;&gt;lb_note_configRoot.Name\" xml:space=\"preserve\">\n    <value>lb_note_configRoot</value>\n  </data>\n  <data name=\"rb_vd_index_0.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>214, 58</value>\n  </data>\n  <data name=\"cb_hk_key.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"tc_Keyboard.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>434, 15</value>\n  </data>\n  <data name=\"btn_RuleEdit.Text\" xml:space=\"preserve\">\n    <value>    Edit...</value>\n  </data>\n  <data name=\"lb_Version.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"gb_profiles.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"tb_configRoot.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>478, 23</value>\n  </data>\n  <data name=\"lb_note_configRoot.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 0, 2, 0</value>\n  </data>\n  <data name=\"MT_General.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1169, 716</value>\n  </data>\n  <data name=\"tbDebug.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>0, 0</value>\n  </data>\n  <data name=\"chb_HideMainViewIfItsShown.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;lb_RunOnStartup.Name\" xml:space=\"preserve\">\n    <value>lb_RunOnStartup</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_1.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>537, 76</value>\n  </data>\n  <data name=\"cb_hk_shift.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"chb_show_vd_index.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>188, 21</value>\n  </data>\n  <data name=\"gb_Rules.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <assembly alias=\"System.Windows.Forms\" name=\"System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089\" />\n  <data name=\"tbEvent.ScrollBars\" type=\"System.Windows.Forms.ScrollBars, System.Windows.Forms\">\n    <value>Vertical</value>\n  </data>\n  <data name=\"chb_HideOnStart.Text\" xml:space=\"preserve\">\n    <value>Hide MainView when program start.</value>\n  </data>\n  <data name=\"tb_hk_tip.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>6</value>\n  </data>\n  <data name=\"tsb_ui.ImageScaling\" type=\"System.Windows.Forms.ToolStripItemImageScaling, System.Windows.Forms\">\n    <value>None</value>\n  </data>\n  <data name=\"btn_m0.Text\" xml:space=\"preserve\">\n    <value>TopLeft to BottomRight, Horizontal</value>\n  </data>\n  <data name=\"&gt;&gt;gb_DesktopArrangement.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"panel_mask.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1275, 28</value>\n  </data>\n  <data name=\"lb_AppName.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"gb_nav.Text\" xml:space=\"preserve\">\n    <value>Navigation</value>\n  </data>\n  <data name=\"&gt;&gt;btn_chooseConfigRoot.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"tb_hk_tip.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"tp_mouse_action.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"btn_PluginSettings.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"tabPage_Genernal_Mouse.Text\" xml:space=\"preserve\">\n    <value>Mouse</value>\n  </data>\n  <data name=\"logTabWarning.Text\" xml:space=\"preserve\">\n    <value>Warning</value>\n  </data>\n  <data name=\"lb_hk_func.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 0, 2, 0</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Plugins.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;llb_TaskScheduler.Parent\" xml:space=\"preserve\">\n    <value>gb_general</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m0.Name\" xml:space=\"preserve\">\n    <value>btn_m0</value>\n  </data>\n  <data name=\"mainTabs.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>1</value>\n  </data>\n  <data name=\"btn_m7.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>272, 236</value>\n  </data>\n  <data name=\"chb_show_vd_index.Text\" xml:space=\"preserve\">\n    <value>Show Virtual Desktop Index</value>\n  </data>\n  <data name=\"&gt;&gt;rb_vdi_on_tray_style_2.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"btn_m3.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>830, 2</value>\n  </data>\n  <data name=\"chb_notify_vd_changed.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"btn_hk_ClearAndSave.Text\" xml:space=\"preserve\">\n    <value>Clear &amp;&amp; Save</value>\n  </data>\n  <data name=\"cb_hk_key.Items58\" xml:space=\"preserve\">\n    <value>F12</value>\n  </data>\n  <data name=\"&gt;&gt;tab_General.Name\" xml:space=\"preserve\">\n    <value>tab_General</value>\n  </data>\n  <data name=\"btn_RuleNew.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>723, 455</value>\n  </data>\n  <data name=\"logTabWarning.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1145, 663</value>\n  </data>\n  <data name=\"&gt;&gt;mainStatusStrip.Name\" xml:space=\"preserve\">\n    <value>mainStatusStrip</value>\n  </data>\n  <data name=\"&gt;&gt;logTabEvent.Name\" xml:space=\"preserve\">\n    <value>logTabEvent</value>\n  </data>\n  <data name=\"&gt;&gt;logTabDebug.Parent\" xml:space=\"preserve\">\n    <value>logTabs</value>\n  </data>\n  <data name=\"cb_hk_win.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"cb_hk_key.Items24\" xml:space=\"preserve\">\n    <value>N</value>\n  </data>\n  <data name=\"&gt;&gt;tsmiMainMenuRestart.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_hk_key.Items26\" xml:space=\"preserve\">\n    <value>P</value>\n  </data>\n  <data name=\"&gt;&gt;pb_AboutLogo.Parent\" xml:space=\"preserve\">\n    <value>MT_About</value>\n  </data>\n  <data name=\"logsToolStripMenuItem.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>139, 22</value>\n  </data>\n  <data name=\"logTabVerbose.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1145, 663</value>\n  </data>\n  <data name=\"lb_nav_circle_h_type.Text\" xml:space=\"preserve\">\n    <value>Right end of row joins to left end of:</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_profiles.Parent\" xml:space=\"preserve\">\n    <value>gb_profiles</value>\n  </data>\n  <data name=\"btn_m7.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"&gt;&gt;showLogsInGuiToolStripMenuItem.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;lb_profiles_note.Parent\" xml:space=\"preserve\">\n    <value>gb_profiles</value>\n  </data>\n  <data name=\"&gt;&gt;lvc_PluginName.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ColumnHeader, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m6.Name\" xml:space=\"preserve\">\n    <value>btn_m6</value>\n  </data>\n  <data name=\"llb_TaskScheduler.Text\" xml:space=\"preserve\">\n    <value>Task Scheduler</value>\n  </data>\n  <data name=\"llb_goto_general.Text\" xml:space=\"preserve\">\n    <value>Go to General page to switch profile.</value>\n  </data>\n  <data name=\"&gt;&gt;tlp_DesktopArrangement.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"gb_DesktopArrangement.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;chb_RunOnStartup.ZOrder\" xml:space=\"preserve\">\n    <value>2</value>\n  </data>\n  <data name=\"logsToolStripMenuItem.Text\" xml:space=\"preserve\">\n    <value>Logs</value>\n  </data>\n  <data name=\"&gt;&gt;panel_Pages.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Panel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"lv_Plugins.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;tab_General.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TabControl, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"MT_About.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>4, 26</value>\n  </data>\n  <data name=\"&gt;&gt;lb_Copyright.ZOrder\" xml:space=\"preserve\">\n    <value>3</value>\n  </data>\n  <data name=\"gb_profiles.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"lb_nav_circle_h_type.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>241, 27</value>\n  </data>\n  <data name=\"&gt;&gt;chb_notify_vd_changed.ZOrder\" xml:space=\"preserve\">\n    <value>5</value>\n  </data>\n  <data name=\"&gt;&gt;tv_mouse.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TreeView, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;gb_CurrentProfile.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"&gt;&gt;btn_hk_ClearAndSave.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"tsb_about.Text\" xml:space=\"preserve\">\n    <value>About</value>\n  </data>\n  <data name=\"tv_keyboard.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;lbVersion.Parent\" xml:space=\"preserve\">\n    <value>MT_About</value>\n  </data>\n  <data name=\"tsb_plugins.ImageTransparentColor\" type=\"System.Drawing.Color, System.Drawing\">\n    <value>Magenta</value>\n  </data>\n  <data name=\"&gt;&gt;gb_general.Name\" xml:space=\"preserve\">\n    <value>gb_general</value>\n  </data>\n  <data name=\"&gt;&gt;tssl_main_tips.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;lb_nav_circle_h_type.Name\" xml:space=\"preserve\">\n    <value>lb_nav_circle_h_type</value>\n  </data>\n  <data name=\"&gt;&gt;cb_RuleProfiles.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"gb_general.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>778, 95</value>\n  </data>\n  <data name=\"&gt;&gt;btn_PluginSettings.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;gb_profiles.Parent\" xml:space=\"preserve\">\n    <value>tabPage_Genernal_Main</value>\n  </data>\n  <data name=\"&gt;&gt;lb_MouseOnTaskbarSwitchDesktop1.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"btn_m5.Text\" xml:space=\"preserve\">\n    <value>TopRight to BottomLeft, Vertical</value>\n  </data>\n  <data name=\"&gt;&gt;tab_General.Parent\" xml:space=\"preserve\">\n    <value>panel_General</value>\n  </data>\n  <data name=\"lb_configRoot.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>22, 26</value>\n  </data>\n  <data name=\"btn_m5.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>278, 242</value>\n  </data>\n  <data name=\"&gt;&gt;logTabDebug.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"&gt;&gt;lb_nav_circle_h_type.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;gb_storage.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"tbError.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>3</value>\n  </data>\n  <data name=\"&gt;&gt;cb_hk_key.ZOrder\" xml:space=\"preserve\">\n    <value>4</value>\n  </data>\n  <data name=\"&gt;&gt;tp_hk_extra.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"&gt;&gt;chb_showVDIndexOnTrayIcon.Name\" xml:space=\"preserve\">\n    <value>chb_showVDIndexOnTrayIcon</value>\n  </data>\n  <data name=\"logTabWarning.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>2</value>\n  </data>\n  <data name=\"tp_mouse_action.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>4, 26</value>\n  </data>\n  <data name=\"chb_HideMainViewIfItsShown.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"MT_UI.Text\" xml:space=\"preserve\">\n    <value>UI</value>\n  </data>\n  <data name=\"cb_hk_key.Items47\" xml:space=\"preserve\">\n    <value>F1</value>\n  </data>\n  <data name=\"lb_Copyright.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>13</value>\n  </data>\n  <data name=\"ts_PageNav.Dock\" type=\"System.Windows.Forms.DockStyle, System.Windows.Forms\">\n    <value>Fill</value>\n  </data>\n  <data name=\"&gt;&gt;toolStripSeparator1.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"lvc_PluginVersion.Text\" xml:space=\"preserve\">\n    <value>Version</value>\n  </data>\n  <data name=\"btn_m4.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;tb_configRoot.ZOrder\" xml:space=\"preserve\">\n    <value>2</value>\n  </data>\n  <data name=\"&gt;&gt;panel_mask.ZOrder\" xml:space=\"preserve\">\n    <value>2</value>\n  </data>\n  <data name=\"logTabInfo.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1145, 663</value>\n  </data>\n  <data name=\"&gt;&gt;tsb_logs.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStripButton, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;chb_HideOnStart.Parent\" xml:space=\"preserve\">\n    <value>gb_Cluster</value>\n  </data>\n  <data name=\"gb_Cluster.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>10, 228</value>\n  </data>\n  <data name=\"runAsAdministratorToolStripMenuItem.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>202, 22</value>\n  </data>\n  <data name=\"&gt;&gt;mainStatusStrip.Parent\" xml:space=\"preserve\">\n    <value>$this</value>\n  </data>\n  <data name=\"&gt;&gt;lb_MouseOnTaskbarSwitchDesktop1.Parent\" xml:space=\"preserve\">\n    <value>tabPage_Genernal_Mouse</value>\n  </data>\n  <data name=\"&gt;&gt;logsToolStripMenuItem.Name\" xml:space=\"preserve\">\n    <value>logsToolStripMenuItem</value>\n  </data>\n  <data name=\"pb_AboutLogo.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>15, 18</value>\n  </data>\n  <data name=\"lb_mouse_action.Text\" xml:space=\"preserve\">\n    <value>LB_MOUSE_ACTION</value>\n  </data>\n  <data name=\"cb_hk_key.Items17\" xml:space=\"preserve\">\n    <value>G</value>\n  </data>\n  <data name=\"cb_nav_circle_v.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"MT_Rules.Text\" xml:space=\"preserve\">\n    <value>Rules</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m0.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"lb_RunOnStartup.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"tv_keyboard.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>10, 15</value>\n  </data>\n  <data name=\"tb_configRoot.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>114, 23</value>\n  </data>\n  <data name=\"cb_RuleProfiles.Enabled\" type=\"System.Boolean, mscorlib\">\n    <value>False</value>\n  </data>\n  <data name=\"&gt;&gt;tsb_general.Name\" xml:space=\"preserve\">\n    <value>tsb_general</value>\n  </data>\n  <data name=\"&gt;&gt;cb_nav_circle_v.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"btn_m5.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"lv_Plugins.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>1</value>\n  </data>\n  <data name=\"mainStatusStrip.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>1, 0, 9, 0</value>\n  </data>\n  <data name=\"tsb_plugins.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>81, 105</value>\n  </data>\n  <data name=\"cb_hk_key.Items27\" xml:space=\"preserve\">\n    <value>Q</value>\n  </data>\n  <data name=\"&gt;&gt;MT_Rules.Parent\" xml:space=\"preserve\">\n    <value>mainTabs</value>\n  </data>\n  <data name=\"llb_TaskScheduler.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>96, 17</value>\n  </data>\n  <data name=\"tsb_about.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n</value>\n  </data>\n  <data name=\"cb_nav_circle_h.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_1.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Cluster.Name\" xml:space=\"preserve\">\n    <value>gb_Cluster</value>\n  </data>\n  <data name=\"cb_hk_key.Items20\" xml:space=\"preserve\">\n    <value>J</value>\n  </data>\n  <data name=\"&gt;&gt;lb_DesktopArrangementNote.Name\" xml:space=\"preserve\">\n    <value>lb_DesktopArrangementNote</value>\n  </data>\n  <data name=\"btn_profile_del.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>3</value>\n  </data>\n  <data name=\"&gt;&gt;mainStatusStrip.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.StatusStrip, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"lb_RunOnStartup.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>323, 17</value>\n  </data>\n  <data name=\"tsb_logs.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n</value>\n  </data>\n  <data name=\"cb_hk_key.Items64\" xml:space=\"preserve\">\n    <value>Home</value>\n  </data>\n  <data name=\"chb_show_vd_name.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"lb_ui_vd_view.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>11, 610</value>\n  </data>\n  <data name=\"&gt;&gt;MT_UI.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"btn_m3.Dock\" type=\"System.Windows.Forms.DockStyle, System.Windows.Forms\">\n    <value>Fill</value>\n  </data>\n  <data name=\"tabPage_Genernal_Keyboard.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>1</value>\n  </data>\n  <data name=\"tb_hk_tip.Multiline\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"cbb_profiles.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>22, 26</value>\n  </data>\n  <data name=\"cb_hk_key.Items57\" xml:space=\"preserve\">\n    <value>F11</value>\n  </data>\n  <data name=\"&gt;&gt;panel_Pages.Parent\" xml:space=\"preserve\">\n    <value>$this</value>\n  </data>\n  <data name=\"tsb_about.TextImageRelation\" type=\"System.Windows.Forms.TextImageRelation, System.Windows.Forms\">\n    <value>ImageAboveText</value>\n  </data>\n  <data name=\"tabPage_Genernal_Main.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>0</value>\n  </data>\n  <data name=\"cb_hk_key.Items8\" xml:space=\"preserve\">\n    <value>D8</value>\n  </data>\n  <data name=\"&gt;&gt;btn_PluginSettings.Name\" xml:space=\"preserve\">\n    <value>btn_PluginSettings</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Rules.Parent\" xml:space=\"preserve\">\n    <value>MT_Rules</value>\n  </data>\n  <data name=\"lb_configRoot.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"&gt;&gt;lb_note_configRoot.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;rb_vdi_on_tray_style_1.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.RadioButton, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_hk_alt.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"&gt;&gt;lb_hk_func.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_hk_key.Items50\" xml:space=\"preserve\">\n    <value>F4</value>\n  </data>\n  <data name=\"btn_chooseConfigRoot.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>101, 24</value>\n  </data>\n  <data name=\"tbInfo.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>2</value>\n  </data>\n  <data name=\"lbox_Env.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>15, 193</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m5.Name\" xml:space=\"preserve\">\n    <value>btn_m5</value>\n  </data>\n  <data name=\"&gt;&gt;tbWarning.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_hk_key.Items22\" xml:space=\"preserve\">\n    <value>L</value>\n  </data>\n  <data name=\"tabPage_Genernal_Main.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>4, 26</value>\n  </data>\n  <data name=\"tc_Keyboard.Visible\" type=\"System.Boolean, mscorlib\">\n    <value>False</value>\n  </data>\n  <data name=\"&gt;&gt;lb_profiles_note.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"tsmiMainMenuRestart.Text\" xml:space=\"preserve\">\n    <value>Restart</value>\n  </data>\n  <data name=\"&gt;&gt;MT_General.Parent\" xml:space=\"preserve\">\n    <value>mainTabs</value>\n  </data>\n  <data name=\"btn_m0.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>272, 236</value>\n  </data>\n  <data name=\"pb_AboutLogo.SizeMode\" type=\"System.Windows.Forms.PictureBoxSizeMode, System.Windows.Forms\">\n    <value>StretchImage</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m0.Parent\" xml:space=\"preserve\">\n    <value>tlp_DesktopArrangement</value>\n  </data>\n  <data name=\"&gt;&gt;tssl_main_tips.Name\" xml:space=\"preserve\">\n    <value>tssl_main_tips</value>\n  </data>\n  <data name=\"MT_Rules.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>4, 26</value>\n  </data>\n  <data name=\"cb_hk_ctrl.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"btn_m5.TextAlign\" type=\"System.Drawing.ContentAlignment, System.Drawing\">\n    <value>BottomCenter</value>\n  </data>\n  <data name=\"lb_MouseOnTaskbarSwitchDesktop1.Text\" xml:space=\"preserve\">\n    <value>Scroll UP =&gt; Go Left                         SHIFT+Scroll Up =&gt; Go Up</value>\n  </data>\n  <data name=\"&gt;&gt;btn_hk_RegAndSave.Name\" xml:space=\"preserve\">\n    <value>btn_hk_RegAndSave</value>\n  </data>\n  <data name=\"lb_hk_extra.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>229, 35</value>\n  </data>\n  <data name=\"MT_General.Text\" xml:space=\"preserve\">\n    <value>General</value>\n  </data>\n  <data name=\"tsb_rules.TextImageRelation\" type=\"System.Windows.Forms.TextImageRelation, System.Windows.Forms\">\n    <value>ImageAboveText</value>\n  </data>\n  <data name=\"cb_hk_win.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"&gt;&gt;btn_RuleEdit.Parent\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <data name=\"tssl_main_tips.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>0, 17</value>\n  </data>\n  <data name=\"cb_hk_key.Items34\" xml:space=\"preserve\">\n    <value>X</value>\n  </data>\n  <data name=\"cb_nav_circle_v.Text\" xml:space=\"preserve\">\n    <value>Circulate vertically. (same col only)</value>\n  </data>\n  <data name=\"&gt;&gt;btn_profile_dup.ZOrder\" xml:space=\"preserve\">\n    <value>3</value>\n  </data>\n  <data name=\"&gt;&gt;chb_RunOnStartup.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;tbWarning.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"lb_DesktopArrangementNote.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>1</value>\n  </data>\n  <data name=\"cb_mouse_func.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>4</value>\n  </data>\n  <data name=\"rb_vd_index_1.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"&gt;&gt;MT_Plugins.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;chb_show_vd_index.Parent\" xml:space=\"preserve\">\n    <value>lb_ui_vd_view</value>\n  </data>\n  <data name=\"tbDebug.Dock\" type=\"System.Windows.Forms.DockStyle, System.Windows.Forms\">\n    <value>Fill</value>\n  </data>\n  <data name=\"tbVerbose.ScrollBars\" type=\"System.Windows.Forms.ScrollBars, System.Windows.Forms\">\n    <value>Vertical</value>\n  </data>\n  <data name=\"&gt;&gt;tsb_logs.Name\" xml:space=\"preserve\">\n    <value>tsb_logs</value>\n  </data>\n  <data name=\"cb_RuleProfiles.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;cb_hk_shift.ZOrder\" xml:space=\"preserve\">\n    <value>5</value>\n  </data>\n  <data name=\"&gt;&gt;MT_Logs.Parent\" xml:space=\"preserve\">\n    <value>mainTabs</value>\n  </data>\n  <data name=\"gb_Rules.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>11, 77</value>\n  </data>\n  <data name=\"&gt;&gt;ts_PageNav.Name\" xml:space=\"preserve\">\n    <value>ts_PageNav</value>\n  </data>\n  <data name=\"cb_hk_alt.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"lb_mouse_action.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>12, 18</value>\n  </data>\n  <data name=\"&gt;&gt;tbError.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"cb_hk_key.Items5\" xml:space=\"preserve\">\n    <value>D5</value>\n  </data>\n  <data name=\"lb_profiles_note.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>22, 58</value>\n  </data>\n  <data name=\"chb_HideOnStart.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>6</value>\n  </data>\n  <data name=\"&gt;&gt;tbVerbose.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;tabPage_Genernal_Keyboard.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;gb_nav.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"tlp_DesktopArrangement.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m7.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;chb_show_vd_index.ZOrder\" xml:space=\"preserve\">\n    <value>2</value>\n  </data>\n  <data name=\"cb_hk_key.Items56\" xml:space=\"preserve\">\n    <value>F10</value>\n  </data>\n  <data name=\"tp_hk_extra.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>1</value>\n  </data>\n  <data name=\"cb_hk_key.Items63\" xml:space=\"preserve\">\n    <value>Tab</value>\n  </data>\n  <data name=\"cb_nav_circle_v.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>226, 21</value>\n  </data>\n  <data name=\"&gt;&gt;openLogFolderToolStripMenuItem.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"gb_CurrentProfile.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>6</value>\n  </data>\n  <data name=\"tabPage_Genernal_Keyboard.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1145, 663</value>\n  </data>\n  <data name=\"cb_hk_key.Items3\" xml:space=\"preserve\">\n    <value>D3</value>\n  </data>\n  <data name=\"&gt;&gt;logTabWarning.Name\" xml:space=\"preserve\">\n    <value>logTabWarning</value>\n  </data>\n  <data name=\"btn_m7.TextAlign\" type=\"System.Drawing.ContentAlignment, System.Drawing\">\n    <value>BottomCenter</value>\n  </data>\n  <data name=\"lb_profiles_note.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 0, 2, 0</value>\n  </data>\n  <data name=\"cb_hk_key.Items19\" xml:space=\"preserve\">\n    <value>I</value>\n  </data>\n  <data name=\"btn_m1.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"logTabDebug.Text\" xml:space=\"preserve\">\n    <value>Debug</value>\n  </data>\n  <data name=\"&gt;&gt;lb_Version.Name\" xml:space=\"preserve\">\n    <value>lb_Version</value>\n  </data>\n  <data name=\"btn_m0.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"btn_m2.FlatStyle\" type=\"System.Windows.Forms.FlatStyle, System.Windows.Forms\">\n    <value>Flat</value>\n  </data>\n  <data name=\"&gt;&gt;cb_hk_alt.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;tabPage_Genernal_Mouse.ZOrder\" xml:space=\"preserve\">\n    <value>2</value>\n  </data>\n  <data name=\"tabPage_Genernal_Keyboard.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>4, 26</value>\n  </data>\n  <data name=\"lbVersion.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>52, 17</value>\n  </data>\n  <data name=\"btn_m5.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;lb_configRoot.Name\" xml:space=\"preserve\">\n    <value>lb_configRoot</value>\n  </data>\n  <data name=\"&gt;&gt;chb_notify_vd_changed.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;cb_RuleProfiles.Parent\" xml:space=\"preserve\">\n    <value>gb_CurrentProfile</value>\n  </data>\n  <data name=\"rb_vd_index_1.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"lv_Rules.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1104, 421</value>\n  </data>\n  <data name=\"tabPage_Genernal_Mouse.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1145, 663</value>\n  </data>\n  <data name=\"btn_m3.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n        QmCC\n</value>\n  </data>\n  <data name=\"MT_About.Text\" xml:space=\"preserve\">\n    <value>About</value>\n  </data>\n  <data name=\"&gt;&gt;llb_Company.Name\" xml:space=\"preserve\">\n    <value>llb_Company</value>\n  </data>\n  <data name=\"lb_mouse_action.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 0, 2, 0</value>\n  </data>\n  <data name=\"&gt;&gt;logTabVerbose.Parent\" xml:space=\"preserve\">\n    <value>logTabs</value>\n  </data>\n  <data name=\"cb_hk_key.Items53\" xml:space=\"preserve\">\n    <value>F7</value>\n  </data>\n  <data name=\"&gt;&gt;mainStatusStrip.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m6.Parent\" xml:space=\"preserve\">\n    <value>tlp_DesktopArrangement</value>\n  </data>\n  <data name=\"lb_MouseOnTaskbarSwitchDesktop1.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>387, 17</value>\n  </data>\n  <data name=\"tp_hk_extra.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"tp_mouse_action.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"btn_m0.TextAlign\" type=\"System.Drawing.ContentAlignment, System.Drawing\">\n    <value>BottomCenter</value>\n  </data>\n  <data name=\"cb_hk_shift.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"btn_RuleEdit.Enabled\" type=\"System.Boolean, mscorlib\">\n    <value>False</value>\n  </data>\n  <data name=\"mainStatusStrip.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1291, 22</value>\n  </data>\n  <data name=\"btn_chooseConfigRoot.Text\" xml:space=\"preserve\">\n    <value>Change...</value>\n  </data>\n  <data name=\"lb_configRoot.Text\" xml:space=\"preserve\">\n    <value>Config Folder</value>\n  </data>\n  <data name=\"lb_MouseOnTaskbarSwitchDesktop2.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>121, 568</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m5.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_hk_win.Text\" xml:space=\"preserve\">\n    <value>Win</value>\n  </data>\n  <data name=\"&gt;&gt;helpToolStripMenuItem.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"panel_UI.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>0, 0</value>\n  </data>\n  <data name=\"chb_RunOnStartup.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>1</value>\n  </data>\n  <data name=\"lb_configRoot.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>87, 17</value>\n  </data>\n  <data name=\"MT_Rules.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>3</value>\n  </data>\n  <data name=\"cbb_profiles.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>356, 25</value>\n  </data>\n  <data name=\"&gt;&gt;logTabs.Parent\" xml:space=\"preserve\">\n    <value>MT_Logs</value>\n  </data>\n  <data name=\"panel_PageNav.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>11, 53</value>\n  </data>\n  <data name=\"btn_m5.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n</value>\n  </data>\n  <data name=\"tlp_DesktopArrangement.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>17, 30</value>\n  </data>\n  <data name=\"btn_m3.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"tsb_ui.TextImageRelation\" type=\"System.Windows.Forms.TextImageRelation, System.Windows.Forms\">\n    <value>ImageAboveText</value>\n  </data>\n  <data name=\"btn_PluginSettings.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>4</value>\n  </data>\n  <data name=\"mainStatusStrip.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>0, 788</value>\n  </data>\n  <data name=\"btn_RuleEdit.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>822, 455</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m3.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;chb_MouseOnTaskbarSwitchDesktop.ZOrder\" xml:space=\"preserve\">\n    <value>4</value>\n  </data>\n  <data name=\"btn_profile_dup.Text\" xml:space=\"preserve\">\n    <value>Dupliate</value>\n  </data>\n  <data name=\"&gt;&gt;MT_About.ZOrder\" xml:space=\"preserve\">\n    <value>5</value>\n  </data>\n  <data name=\"lb_MouseOnTaskbarSwitchDesktop2.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"btn_m0.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>0</value>\n  </data>\n  <data name=\"logTabEvent.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>4, 26</value>\n  </data>\n  <data name=\"cb_hk_win.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_0.Text\" xml:space=\"preserve\">\n    <value>Default</value>\n  </data>\n  <data name=\"btn_m6.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"&gt;&gt;lb_mouse_action.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"&gt;&gt;btn_hk_ClearAndSave.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"tsmiMainMenuQuit.Text\" xml:space=\"preserve\">\n    <value>Shutdown Application</value>\n  </data>\n  <data name=\"&gt;&gt;lb_hk_func.Name\" xml:space=\"preserve\">\n    <value>lb_hk_func</value>\n  </data>\n  <data name=\"&gt;&gt;gb_storage.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"cb_hk_key.Items12\" xml:space=\"preserve\">\n    <value>B</value>\n  </data>\n  <data name=\"&gt;&gt;btn_profile_rename.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_hk_key.Items44\" xml:space=\"preserve\">\n    <value>NumPad8</value>\n  </data>\n  <data name=\"openLogFolderToolStripMenuItem.Text\" xml:space=\"preserve\">\n    <value>Open Logs Folder...</value>\n  </data>\n  <data name=\"&gt;&gt;chb_HideMainViewIfItsShown.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"tsb_plugins.Text\" xml:space=\"preserve\">\n    <value>Plugins</value>\n  </data>\n  <data name=\"cb_hk_key.Items9\" xml:space=\"preserve\">\n    <value>D9</value>\n  </data>\n  <data name=\"&gt;&gt;lb_RunOnStartup.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"btn_m6.FlatStyle\" type=\"System.Windows.Forms.FlatStyle, System.Windows.Forms\">\n    <value>Flat</value>\n  </data>\n  <data name=\"&gt;&gt;tabPage_Genernal_Keyboard.Name\" xml:space=\"preserve\">\n    <value>tabPage_Genernal_Keyboard</value>\n  </data>\n  <data name=\"&gt;&gt;llb_TaskScheduler.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"chb_MouseOnTaskbarSwitchDesktop.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"tbWarning.Dock\" type=\"System.Windows.Forms.DockStyle, System.Windows.Forms\">\n    <value>Fill</value>\n  </data>\n  <data name=\"&gt;&gt;cb_hk_win.ZOrder\" xml:space=\"preserve\">\n    <value>8</value>\n  </data>\n  <data name=\"&gt;&gt;gb_storage.Parent\" xml:space=\"preserve\">\n    <value>tabPage_Genernal_Main</value>\n  </data>\n  <data name=\"langToolStripMenuItem.Text\" xml:space=\"preserve\">\n    <value>Languages</value>\n  </data>\n  <data name=\"tp_hk_extra.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>492, 470</value>\n  </data>\n  <data name=\"lb_ui_vd_view.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>388, 92</value>\n  </data>\n  <data name=\"lb_Version.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>12</value>\n  </data>\n  <data name=\"btn_mouse_save.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>13, 81</value>\n  </data>\n  <data name=\"&gt;&gt;rb_vd_index_1.Parent\" xml:space=\"preserve\">\n    <value>lb_ui_vd_view</value>\n  </data>\n  <data name=\"&gt;&gt;lbox_Env.Parent\" xml:space=\"preserve\">\n    <value>MT_About</value>\n  </data>\n  <data name=\"&gt;&gt;MT_UI.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;btn_profile_dup.Parent\" xml:space=\"preserve\">\n    <value>gb_profiles</value>\n  </data>\n  <data name=\"&gt;&gt;logTabDebug.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"btn_m4.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>4</value>\n  </data>\n  <data name=\"tab_General.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>8, 14</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_2.Text\" xml:space=\"preserve\">\n    <value>High Contrast 2</value>\n  </data>\n  <data name=\"&gt;&gt;lb_MouseOnTaskbarSwitchDesktop1.Name\" xml:space=\"preserve\">\n    <value>lb_MouseOnTaskbarSwitchDesktop1</value>\n  </data>\n  <data name=\"cb_hk_win.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;aboutToolStripMenuItem.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"btn_RuleRemove.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>6, 0, 0, 0</value>\n  </data>\n  <data name=\"cb_hk_shift.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;MT_Logs.ZOrder\" xml:space=\"preserve\">\n    <value>4</value>\n  </data>\n  <data name=\"btn_m6.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>272, 236</value>\n  </data>\n  <data name=\"cb_hk_key.Items62\" xml:space=\"preserve\">\n    <value>Down</value>\n  </data>\n  <data name=\"chb_RunOnStartup.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"btn_m6.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>554, 242</value>\n  </data>\n  <data name=\"chb_show_vd_name.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>191, 21</value>\n  </data>\n  <data name=\"&gt;&gt;btn_PluginSettings.Parent\" xml:space=\"preserve\">\n    <value>gb_Plugins</value>\n  </data>\n  <data name=\"gb_Plugins.Text\" xml:space=\"preserve\">\n    <value>Plugins</value>\n  </data>\n  <data name=\"tc_Mouse.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>500, 500</value>\n  </data>\n  <data name=\"tc_Keyboard.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;logCMS.Name\" xml:space=\"preserve\">\n    <value>logCMS</value>\n  </data>\n  <data name=\"tbInfo.ScrollBars\" type=\"System.Windows.Forms.ScrollBars, System.Windows.Forms\">\n    <value>Vertical</value>\n  </data>\n  <data name=\"lb_RunOnStartup.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>22, 59</value>\n  </data>\n  <data name=\"&gt;&gt;logTabs.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TabControl, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"btn_m2.Dock\" type=\"System.Windows.Forms.DockStyle, System.Windows.Forms\">\n    <value>Fill</value>\n  </data>\n  <data name=\"cb_nav_circle_h_type.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"openLogFolderToolStripMenuItem.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>203, 22</value>\n  </data>\n  <data name=\"&gt;&gt;logTabWarning.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"btn_RuleRemove.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>1020, 455</value>\n  </data>\n  <data name=\"panel_UI.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1169, 716</value>\n  </data>\n  <data name=\"&gt;&gt;tb_configRoot.Parent\" xml:space=\"preserve\">\n    <value>gb_storage</value>\n  </data>\n  <data name=\"&gt;&gt;lb_AppName.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"cb_hk_shift.Text\" xml:space=\"preserve\">\n    <value>Shift</value>\n  </data>\n  <data name=\"gb_profiles.Text\" xml:space=\"preserve\">\n    <value>Profiles</value>\n  </data>\n  <data name=\"tsb_about.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>81, 105</value>\n  </data>\n  <data name=\"btn_RuleRemove.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"rb_vd_index_0.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"btn_profile_dup.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>101, 25</value>\n  </data>\n  <data name=\"tbEvent.Multiline\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"btn_RuleRemove.ImageAlign\" type=\"System.Drawing.ContentAlignment, System.Drawing\">\n    <value>MiddleLeft</value>\n  </data>\n  <data name=\"logTabDebug.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1145, 663</value>\n  </data>\n  <data name=\"cb_hk_key.Items18\" xml:space=\"preserve\">\n    <value>H</value>\n  </data>\n  <data name=\"cb_hk_key.Items15\" xml:space=\"preserve\">\n    <value>E</value>\n  </data>\n  <data name=\"cb_hk_key.Items65\" xml:space=\"preserve\">\n    <value>End</value>\n  </data>\n  <data name=\"&gt;&gt;llb_Company.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.LinkLabel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_1.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>8</value>\n  </data>\n  <data name=\"&gt;&gt;rb_vdi_on_tray_style_0.Name\" xml:space=\"preserve\">\n    <value>rb_vdi_on_tray_style_0</value>\n  </data>\n  <data name=\"&gt;&gt;optionsToolStripMenuItem.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"btn_m1.FlatStyle\" type=\"System.Windows.Forms.FlatStyle, System.Windows.Forms\">\n    <value>Flat</value>\n  </data>\n  <data name=\"tbInfo.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1145, 663</value>\n  </data>\n  <data name=\"btn_m6.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n        aHy4C99++gc4d8SX26+Q+QAAAABJRU5ErkJggg==\n</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m2.Parent\" xml:space=\"preserve\">\n    <value>tlp_DesktopArrangement</value>\n  </data>\n  <data name=\"&gt;&gt;aboutToolStripMenuItem.Name\" xml:space=\"preserve\">\n    <value>aboutToolStripMenuItem</value>\n  </data>\n  <data name=\"lb_MouseOnTaskbarSwitchDesktop1.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"lb_RunOnStartup.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 0, 2, 0</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m4.ZOrder\" xml:space=\"preserve\">\n    <value>3</value>\n  </data>\n  <data name=\"gb_Rules.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"tsb_about.ImageTransparentColor\" type=\"System.Drawing.Color, System.Drawing\">\n    <value>Magenta</value>\n  </data>\n  <data name=\"&gt;&gt;cb_nav_circle_h_type.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;lb_Version.Parent\" xml:space=\"preserve\">\n    <value>MT_About</value>\n  </data>\n  <data name=\"tabPage_Genernal_Keyboard.Text\" xml:space=\"preserve\">\n    <value>Keyboard</value>\n  </data>\n  <data name=\"tsb_ui.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_1.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>117, 21</value>\n  </data>\n  <data name=\"panel_UI.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;MT_Logs.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;panel_mask.Parent\" xml:space=\"preserve\">\n    <value>$this</value>\n  </data>\n  <data name=\"cb_nav_circle_h_type.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>472, 24</value>\n  </data>\n  <data name=\"MT_General.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>4, 26</value>\n  </data>\n  <data name=\"&gt;&gt;tsb_rules.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStripButton, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"lb_AppName.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>452, 82</value>\n  </data>\n  <data name=\"&gt;&gt;lb_hk_func.Parent\" xml:space=\"preserve\">\n    <value>tp_hk_main</value>\n  </data>\n  <data name=\"lvc_PluginEmail.Text\" xml:space=\"preserve\">\n    <value>Email</value>\n  </data>\n  <data name=\"&gt;&gt;tsb_rules.Name\" xml:space=\"preserve\">\n    <value>tsb_rules</value>\n  </data>\n  <data name=\"logTabError.Text\" xml:space=\"preserve\">\n    <value>Error</value>\n  </data>\n  <data name=\"tabPage_Genernal_Mouse.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>2</value>\n  </data>\n  <data name=\"gb_Rules.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>7</value>\n  </data>\n  <data name=\"tc_Mouse.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;tbError.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;lb_Copyright.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"mainMenu.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>0, 0</value>\n  </data>\n  <data name=\"&gt;&gt;mainTabs.Parent\" xml:space=\"preserve\">\n    <value>panel_Pages</value>\n  </data>\n  <data name=\"lbVersion.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"&gt;&gt;tb_configRoot.Name\" xml:space=\"preserve\">\n    <value>tb_configRoot</value>\n  </data>\n  <data name=\"&gt;&gt;lvc_PluginAuthor.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ColumnHeader, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"btn_RuleRemove.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAu\n        IgAALiIBquLdkgAAAWJJREFUSEvt1r1KA0EYheHF3yakSCM2NhZiwE5R0cpKRcktWHsJYiGIegmCpdgK\n        IooI4gUIXoE2AX9BMIKIlfE9w3w6yGx015RbPAl7ZuY7YQPJJs0kaaUPZ2jiHa8BXX/gHP2InXeiYeAC\n        KvjNJWLnnWjorcOG7GAEs5jz77rehu3ZQmyOeyljEANeJ+Zhh1+Qdjt0O59hexfQAZuluWVtrMM2xaik\n        8SML1yS2ZuoqSRvQLg2VVLAShHsYgu59Vjq3C5u1iord2zEfyprP8tJgmzWhzBZalSxiE+5AYBwbqAWZ\n        ZC7pwi2Un/jMHEH5A3p8JplLunEH5ac+M8dQ/ohen0lR4vKi5GuhKFH+7xL9t9xAuYZaLodQfg99GMsz\n        l8gUllENMhmG8ukgk1wlWaWWjPpQDjCDpRx0bh82S7/UrkBK0Bdoi+3wBD0/cPVNrVfQhjeEz1h/pXN6\n        FrvGJJibJJ8pRI1RloGcIgAAAABJRU5ErkJggg==\n</value>\n  </data>\n  <data name=\"lbVersion.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"btn_RuleClone.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>95, 40</value>\n  </data>\n  <data name=\"btn_m4.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>272, 236</value>\n  </data>\n  <data name=\"&gt;&gt;rb_vdi_on_tray_style_2.Name\" xml:space=\"preserve\">\n    <value>rb_vdi_on_tray_style_2</value>\n  </data>\n  <data name=\"cb_hk_win.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>49, 21</value>\n  </data>\n  <data name=\"&gt;&gt;tabPage_Genernal_Main.Parent\" xml:space=\"preserve\">\n    <value>tab_General</value>\n  </data>\n  <data name=\"lb_Version.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 0, 2, 0</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Rules.Name\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <data name=\"&gt;&gt;tbEvent.Name\" xml:space=\"preserve\">\n    <value>tbEvent</value>\n  </data>\n  <data name=\"cb_hk_key.Items2\" xml:space=\"preserve\">\n    <value>D2</value>\n  </data>\n  <data name=\"rb_vd_index_1.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"cb_hk_key.Items54\" xml:space=\"preserve\">\n    <value>F8</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_2.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>117, 21</value>\n  </data>\n  <data name=\"&gt;&gt;tbInfo.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"btn_hk_RegAndSave.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>143, 36</value>\n  </data>\n  <data name=\"cb_hk_ctrl.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>64, 47</value>\n  </data>\n  <data name=\"rb_vd_index_1.Text\" xml:space=\"preserve\">\n    <value>1-based</value>\n  </data>\n  <data name=\"&gt;&gt;cb_nav_circle_h_type.Parent\" xml:space=\"preserve\">\n    <value>gb_nav</value>\n  </data>\n  <data name=\"lb_Version.Text\" xml:space=\"preserve\">\n    <value>Version</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m4.Name\" xml:space=\"preserve\">\n    <value>btn_m4</value>\n  </data>\n  <data name=\"tsb_about.ImageScaling\" type=\"System.Windows.Forms.ToolStripItemImageScaling, System.Windows.Forms\">\n    <value>None</value>\n  </data>\n  <data name=\"&gt;&gt;mainMenu.Name\" xml:space=\"preserve\">\n    <value>mainMenu</value>\n  </data>\n  <data name=\"tsb_rules.ImageScaling\" type=\"System.Windows.Forms.ToolStripItemImageScaling, System.Windows.Forms\">\n    <value>None</value>\n  </data>\n  <data name=\"&gt;&gt;logTabVerbose.Name\" xml:space=\"preserve\">\n    <value>logTabVerbose</value>\n  </data>\n  <data name=\"chb_MouseOnTaskbarSwitchDesktop.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>10, 529</value>\n  </data>\n  <data name=\"lbVersion.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>11</value>\n  </data>\n  <data name=\"&gt;&gt;tc_Keyboard.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TabControl, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;mainMenu.Parent\" xml:space=\"preserve\">\n    <value>$this</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Cluster.ZOrder\" xml:space=\"preserve\">\n    <value>4</value>\n  </data>\n  <data name=\"panel_Pages.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>102, 27</value>\n  </data>\n  <data name=\"tlp_DesktopArrangement.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1104, 480</value>\n  </data>\n  <data name=\"lb_mouse_action.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>127, 17</value>\n  </data>\n  <data name=\"panel_Pages.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1177, 746</value>\n  </data>\n  <data name=\"&gt;&gt;btn_RuleRemove.ZOrder\" xml:space=\"preserve\">\n    <value>4</value>\n  </data>\n  <data name=\"lvc_Created.Text\" xml:space=\"preserve\">\n    <value>Created</value>\n  </data>\n  <data name=\"&gt;&gt;lb_AppName.Name\" xml:space=\"preserve\">\n    <value>lb_AppName</value>\n  </data>\n  <data name=\"btn_hk_ClearAndSave.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"&gt;&gt;lb_ui_vd_view.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"chb_RunOnStartup.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_0.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>7</value>\n  </data>\n  <data name=\"logCMS.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>107, 26</value>\n  </data>\n  <data name=\"tp_hk_main.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>4, 26</value>\n  </data>\n  <data name=\"gb_nav.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;chb_show_vd_index.Name\" xml:space=\"preserve\">\n    <value>chb_show_vd_index</value>\n  </data>\n  <data name=\"tc_Keyboard.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>1</value>\n  </data>\n  <data name=\"pb_AboutLogo.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>81, 91</value>\n  </data>\n  <data name=\"MT_Logs.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1169, 716</value>\n  </data>\n  <data name=\"tbDebug.WordWrap\" type=\"System.Boolean, mscorlib\">\n    <value>False</value>\n  </data>\n  <data name=\"&gt;&gt;rb_vd_index_1.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"lbox_Env.ItemHeight\" type=\"System.Int32, mscorlib\">\n    <value>17</value>\n  </data>\n  <data name=\"tsmiMainMenuQuit.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>202, 22</value>\n  </data>\n  <data name=\"btn_m7.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>7</value>\n  </data>\n  <data name=\"btn_RuleClone.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"tbError.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>0, 0</value>\n  </data>\n  <data name=\"tp_hk_main.Text\" xml:space=\"preserve\">\n    <value>Hotkey</value>\n  </data>\n  <data name=\"optionsToolStripMenuItem.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>66, 21</value>\n  </data>\n  <data name=\"rb_vd_index_0.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>2</value>\n  </data>\n  <data name=\"gb_Cluster.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>3</value>\n  </data>\n  <data name=\"lb_mouse_action.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>7</value>\n  </data>\n  <data name=\"btn_m3.FlatStyle\" type=\"System.Windows.Forms.FlatStyle, System.Windows.Forms\">\n    <value>Flat</value>\n  </data>\n  <data name=\"tbEvent.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>0, 0</value>\n  </data>\n  <data name=\"&gt;&gt;lvc_PluginName.Name\" xml:space=\"preserve\">\n    <value>lvc_PluginName</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_0.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>67, 21</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Rules.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"tsb_general.ImageScaling\" type=\"System.Windows.Forms.ToolStripItemImageScaling, System.Windows.Forms\">\n    <value>None</value>\n  </data>\n  <data name=\"gb_Plugins.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1137, 549</value>\n  </data>\n  <data name=\"pb_AboutLogo.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>9</value>\n  </data>\n  <data name=\"&gt;&gt;tc_Mouse.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TabControl, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;cb_hk_shift.Parent\" xml:space=\"preserve\">\n    <value>tp_hk_main</value>\n  </data>\n  <data name=\"&gt;&gt;logTabError.ZOrder\" xml:space=\"preserve\">\n    <value>5</value>\n  </data>\n  <data name=\"chb_showVDIndexOnTrayIcon.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"tp_hk_main.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>0</value>\n  </data>\n  <data name=\"MT_Logs.Text\" xml:space=\"preserve\">\n    <value>Logs</value>\n  </data>\n  <data name=\"lb_hk_func.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>7</value>\n  </data>\n  <data name=\"&gt;&gt;tv_keyboard.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"tbWarning.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1145, 663</value>\n  </data>\n  <data name=\"&gt;&gt;cb_nav_circle_h.ZOrder\" xml:space=\"preserve\">\n    <value>3</value>\n  </data>\n  <data name=\"panel_PageNav.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>83, 718</value>\n  </data>\n  <data name=\"&gt;&gt;ts_PageNav.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStrip, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_hk_key.Items45\" xml:space=\"preserve\">\n    <value>NumPad9</value>\n  </data>\n  <data name=\"&gt;&gt;gb_general.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"helpToolStripMenuItem.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>47, 21</value>\n  </data>\n  <data name=\"tbDebug.Multiline\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"&gt;&gt;btn_RuleNew.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;tp_hk_main.Parent\" xml:space=\"preserve\">\n    <value>tc_Keyboard</value>\n  </data>\n  <data name=\"&gt;&gt;btn_RuleRemove.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"btn_m1.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>272, 236</value>\n  </data>\n  <data name=\"lb_Copyright.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"&gt;&gt;tp_hk_main.Name\" xml:space=\"preserve\">\n    <value>tp_hk_main</value>\n  </data>\n  <data name=\"tp_hk_extra.Text\" xml:space=\"preserve\">\n    <value>Alternate</value>\n  </data>\n  <data name=\"&gt;&gt;btn_RuleNew.ZOrder\" xml:space=\"preserve\">\n    <value>3</value>\n  </data>\n  <data name=\"ts_PageNav.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>0, 0</value>\n  </data>\n  <data name=\"cbb_profiles.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;cb_nav_circle_h.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_hk_shift.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>52, 21</value>\n  </data>\n  <data name=\"logTabs.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>8, 14</value>\n  </data>\n  <data name=\"btn_RuleRemove.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"lb_nav_circle_h_type.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>220, 17</value>\n  </data>\n  <data name=\"&gt;&gt;lbVersion.ZOrder\" xml:space=\"preserve\">\n    <value>5</value>\n  </data>\n  <data name=\"chb_notify_vd_changed.Text\" xml:space=\"preserve\">\n    <value>Show notification when Current virtual desktop changed.</value>\n  </data>\n  <data name=\"&gt;&gt;lb_note_configRoot.Parent\" xml:space=\"preserve\">\n    <value>gb_storage</value>\n  </data>\n  <data name=\"lb_MouseOnTaskbarSwitchDesktop1.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>4</value>\n  </data>\n  <data name=\"&gt;&gt;fileToolStripMenuItem.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"gb_profiles.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>778, 120</value>\n  </data>\n  <data name=\"btn_profile_rename.Text\" xml:space=\"preserve\">\n    <value>Rename</value>\n  </data>\n  <data name=\"&gt;&gt;cb_hk_alt.Parent\" xml:space=\"preserve\">\n    <value>tp_hk_main</value>\n  </data>\n  <data name=\"lb_nav_circle_h_type.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>3</value>\n  </data>\n  <data name=\"&gt;&gt;gb_nav.Name\" xml:space=\"preserve\">\n    <value>gb_nav</value>\n  </data>\n  <data name=\"cb_hk_key.Items32\" xml:space=\"preserve\">\n    <value>V</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_2.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>655, 76</value>\n  </data>\n  <data name=\"cb_hk_key.Items21\" xml:space=\"preserve\">\n    <value>K</value>\n  </data>\n  <data name=\"&gt;&gt;tbWarning.Parent\" xml:space=\"preserve\">\n    <value>logTabWarning</value>\n  </data>\n  <data name=\"&gt;&gt;tp_mouse_action.Name\" xml:space=\"preserve\">\n    <value>tp_mouse_action</value>\n  </data>\n  <data name=\"&gt;&gt;lvc_Created.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ColumnHeader, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"logTabInfo.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>4, 26</value>\n  </data>\n  <data name=\"gb_CurrentProfile.Text\" xml:space=\"preserve\">\n    <value>Current Profile</value>\n  </data>\n  <data name=\"&gt;&gt;chb_MouseOnTaskbarSwitchDesktop.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m2.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"lb_hk_func.Text\" xml:space=\"preserve\">\n    <value>LB_HK_FUNC</value>\n  </data>\n  <data name=\"&gt;&gt;lv_Plugins.Parent\" xml:space=\"preserve\">\n    <value>gb_Plugins</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m6.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;tlp_DesktopArrangement.Parent\" xml:space=\"preserve\">\n    <value>gb_DesktopArrangement</value>\n  </data>\n  <data name=\"lbox_Env.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>516, 123</value>\n  </data>\n  <data name=\"&gt;&gt;tsb_general.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStripButton, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;gb_general.ZOrder\" xml:space=\"preserve\">\n    <value>2</value>\n  </data>\n  <data name=\"&gt;&gt;tb_configRoot.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"chb_showVDIndexOnTrayIcon.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>22, 75</value>\n  </data>\n  <data name=\"&gt;&gt;tc_Mouse.ZOrder\" xml:space=\"preserve\">\n    <value>3</value>\n  </data>\n  <data name=\"MT_Rules.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;lb_MouseOnTaskbarSwitchDesktop2.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m1.Parent\" xml:space=\"preserve\">\n    <value>tlp_DesktopArrangement</value>\n  </data>\n  <data name=\"&gt;&gt;logTabError.Parent\" xml:space=\"preserve\">\n    <value>logTabs</value>\n  </data>\n  <data name=\"btn_chooseConfigRoot.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>598, 22</value>\n  </data>\n  <data name=\"tp_mouse_action.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>492, 470</value>\n  </data>\n  <data name=\"&gt;&gt;tp_hk_main.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"btn_RuleNew.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>95, 40</value>\n  </data>\n  <data name=\"lb_note_configRoot.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"llb_goto_general.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"gb_general.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"lb_AppName.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>102, 19</value>\n  </data>\n  <data name=\"chb_show_vd_index.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"tc_Mouse.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>2</value>\n  </data>\n  <data name=\"panel_PageNav.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>4</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m3.Parent\" xml:space=\"preserve\">\n    <value>tlp_DesktopArrangement</value>\n  </data>\n  <data name=\"&gt;&gt;tsmiMainMenuQuit.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"MT_General.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>0</value>\n  </data>\n  <data name=\"tv_mouse.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;chb_showVDIndexOnTrayIcon.Parent\" xml:space=\"preserve\">\n    <value>gb_Cluster</value>\n  </data>\n  <data name=\"&gt;&gt;MT_Rules.Name\" xml:space=\"preserve\">\n    <value>MT_Rules</value>\n  </data>\n  <data name=\"cb_hk_alt.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>42, 21</value>\n  </data>\n  <data name=\"&gt;&gt;lv_Plugins.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;mainMenu.ZOrder\" xml:space=\"preserve\">\n    <value>5</value>\n  </data>\n  <data name=\"&gt;&gt;runAsAdministratorToolStripMenuItem.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"btn_RuleClone.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAu\n        IgAALiIBquLdkgAAASdJREFUSEvt1j9KA0EUx/EtvIOQ2gi2Eey0srAxGARFEVG8gYUnsPAaNrmJVmlj\n        qXeQEPy//r7DezDGCWwmI1ik+Cy8md33IzOTTap6UKWcyKOM5vAsd9JOBaxKXdBDKuRQ/IYruch0K6FP\n        KmRdPCQ139S20GPsA23Zla5cC5Nf0pL4wVmcCX1GFEdWTHqTYiFjKya9S7EQloWCTaapT6JYCGeaYl+o\n        N63+kxCOHTWbvwiJLUJm8r9Clmwsx55MDTmwGh1ZznQp9PhMhcTf+HBTQ6/mw2p//iUVgr6NlXA6LQRb\n        0mvoXPxFe2Nj7MmahGb+qt9hYA4sE302orGACxPgN5ljl4NN9k9yLL9ChuJBJYQlinFZkXvhfxL7k+tJ\n        2JsfAfWgqr4BuhhlyEKF8m4AAAAASUVORK5CYII=\n</value>\n  </data>\n  <data name=\"tbError.Multiline\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"btn_m7.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"cb_hk_key.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>4</value>\n  </data>\n  <data name=\"cb_mouse_func.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;tp_mouse_action.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"tbWarning.Multiline\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"tbEvent.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1145, 663</value>\n  </data>\n  <data name=\"&gt;&gt;tb_hk_tip.Parent\" xml:space=\"preserve\">\n    <value>tp_hk_main</value>\n  </data>\n  <data name=\"btn_profile_dup.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>384, 25</value>\n  </data>\n  <data name=\"tbInfo.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>0, 0</value>\n  </data>\n  <data name=\"lb_AppName.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 0, 2, 0</value>\n  </data>\n  <data name=\"&gt;&gt;lb_Copyright.Name\" xml:space=\"preserve\">\n    <value>lb_Copyright</value>\n  </data>\n  <data name=\"&gt;&gt;lb_DesktopArrangementNote.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"tlp_DesktopArrangement.RowCount\" type=\"System.Int32, mscorlib\">\n    <value>2</value>\n  </data>\n  <data name=\"btn_m1.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>1</value>\n  </data>\n  <data name=\"llb_TaskScheduler.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>3</value>\n  </data>\n  <data name=\"&gt;&gt;cb_hk_win.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"lbVersion.Text\" xml:space=\"preserve\">\n    <value>Version</value>\n  </data>\n  <data name=\"&gt;&gt;gb_CurrentProfile.Parent\" xml:space=\"preserve\">\n    <value>MT_Rules</value>\n  </data>\n  <data name=\"logTabVerbose.Text\" xml:space=\"preserve\">\n    <value>Verbose</value>\n  </data>\n  <data name=\"lb_AppName.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"&gt;&gt;chb_HideOnStart.Name\" xml:space=\"preserve\">\n    <value>chb_HideOnStart</value>\n  </data>\n  <data name=\"tbVerbose.Multiline\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"&gt;&gt;logCMS.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"clearToolStripMenuItem.Text\" xml:space=\"preserve\">\n    <value>Clear</value>\n  </data>\n  <data name=\"cb_hk_key.Items55\" xml:space=\"preserve\">\n    <value>F9</value>\n  </data>\n  <data name=\"&gt;&gt;rb_vdi_on_tray_style_2.Parent\" xml:space=\"preserve\">\n    <value>gb_Cluster</value>\n  </data>\n  <data name=\"&gt;&gt;clearToolStripMenuItem.Name\" xml:space=\"preserve\">\n    <value>clearToolStripMenuItem</value>\n  </data>\n  <data name=\"lb_hk_extra.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;llb_Company.Parent\" xml:space=\"preserve\">\n    <value>MT_About</value>\n  </data>\n  <data name=\"&gt;&gt;tc_Keyboard.Name\" xml:space=\"preserve\">\n    <value>tc_Keyboard</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_profiles.Name\" xml:space=\"preserve\">\n    <value>cbb_profiles</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m1.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"tlp_DesktopArrangement.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>2</value>\n  </data>\n  <data name=\"btn_PluginSettings.Text\" xml:space=\"preserve\">\n    <value>    Settings</value>\n  </data>\n  <data name=\"&gt;&gt;btn_profile_rename.Parent\" xml:space=\"preserve\">\n    <value>gb_profiles</value>\n  </data>\n  <data name=\"&gt;&gt;panel_UI.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;helpToolStripMenuItem.Name\" xml:space=\"preserve\">\n    <value>helpToolStripMenuItem</value>\n  </data>\n  <data name=\"btn_m1.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>278, 2</value>\n  </data>\n  <data name=\"btn_RuleClone.Enabled\" type=\"System.Boolean, mscorlib\">\n    <value>False</value>\n  </data>\n  <data name=\"&gt;&gt;tsb_about.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStripButton, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"rb_vd_index_0.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;ts_PageNav.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"mainMenu.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;logTabInfo.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;llb_goto_general.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.LinkLabel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;chb_show_vd_name.Name\" xml:space=\"preserve\">\n    <value>chb_show_vd_name</value>\n  </data>\n  <data name=\"btn_RuleEdit.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAu\n        IgAALiIBquLdkgAAAbhJREFUSEut1r8rRWEcx/EzsGBgY6EkCxnIYDFJMphMpMjAoDAZDEpmi6KwKH8D\n        m2Rh8DMhKRsZWFAkOt6f7nPufTzOee653OFV3+f7fJ/zud3TOfcGQRAWUzkO8YA+08PPof+oxAlYZHWA\n        vd/Df7UBih8+0KDNOmzhvAAXuEYJopA2fMEOkRttHjnNtDah8yu4NHUL7BkjtpmXvhqdHbF626bXa/Vk\n        Wc1Xs9Cn6U6hCzqn2r6YrEJ7Y2Z9kFkH4bNp7GQaqTSBItYcNDOMqkydC9nPNPKqxRtYJBqFdaawkDLc\n        gUWiT3TCOldYyDEovNrhnEsfomeJwst6ldjShayDwmsccWeRP2QeFF4LiDtr+EOGoD2fNWh2Ev2mdvhD\n        9OxoL4nuk+Z6zHrJrB3+kD1oL84pNMNbNtubMD2HP+QK2nPdowKa0Q2P+lOm50gO0UXeoT2bnnb9PERz\n        g4j2Cg7Re0f9yBP0FbkP2wCimbwhu7lmVjUaUWr1XPbbODHkBVThGZod+mOgAP1+16Ae7swMdF6m4QRI\n        bqAYZuEESBDegqoo9KvoBEgQtkJ/DHRv/uoRi3AuLmHwDTVanr01N1gtAAAAAElFTkSuQmCC\n</value>\n  </data>\n  <data name=\"&gt;&gt;gb_nav.ZOrder\" xml:space=\"preserve\">\n    <value>3</value>\n  </data>\n  <data name=\"gb_general.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>5</value>\n  </data>\n  <data name=\"gb_Cluster.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"btn_m6.Dock\" type=\"System.Windows.Forms.DockStyle, System.Windows.Forms\">\n    <value>Fill</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Plugins.Parent\" xml:space=\"preserve\">\n    <value>MT_Plugins</value>\n  </data>\n  <data name=\"tsb_ui.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>81, 105</value>\n  </data>\n  <data name=\"&gt;&gt;rb_vdi_on_tray_style_0.ZOrder\" xml:space=\"preserve\">\n    <value>2</value>\n  </data>\n  <data name=\"btn_RuleClone.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>6, 0, 0, 0</value>\n  </data>\n  <data name=\"btn_hk_RegAndSave.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>8</value>\n  </data>\n  <data name=\"&gt;&gt;btn_RuleEdit.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_hk_key.Items23\" xml:space=\"preserve\">\n    <value>M</value>\n  </data>\n  <data name=\"&gt;&gt;btn_hk_RegAndSave.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;gb_DesktopArrangement.Parent\" xml:space=\"preserve\">\n    <value>panel_UI</value>\n  </data>\n  <data name=\"&gt;&gt;panel_Pages.Name\" xml:space=\"preserve\">\n    <value>panel_Pages</value>\n  </data>\n  <data name=\"MT_Plugins.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>4, 26</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m7.Name\" xml:space=\"preserve\">\n    <value>btn_m7</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m7.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"btn_m4.Dock\" type=\"System.Windows.Forms.DockStyle, System.Windows.Forms\">\n    <value>Fill</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m4.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;cb_hk_shift.Name\" xml:space=\"preserve\">\n    <value>cb_hk_shift</value>\n  </data>\n  <data name=\"cb_hk_ctrl.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"lb_MouseOnTaskbarSwitchDesktop2.Text\" xml:space=\"preserve\">\n    <value>Scroll Down =&gt; Go Right                 SHIFT+Scroll Down =&gt; Go Down</value>\n  </data>\n  <data name=\"cb_hk_shift.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>158, 47</value>\n  </data>\n  <data name=\"&gt;&gt;tbDebug.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;chb_notify_vd_changed.Name\" xml:space=\"preserve\">\n    <value>chb_notify_vd_changed</value>\n  </data>\n  <data name=\"&gt;&gt;tv_keyboard.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TreeView, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;lvc_Updated.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ColumnHeader, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_hk_key.Items29\" xml:space=\"preserve\">\n    <value>S</value>\n  </data>\n  <data name=\"&gt;&gt;panel_PageNav.Parent\" xml:space=\"preserve\">\n    <value>$this</value>\n  </data>\n  <data name=\"&gt;&gt;lb_Copyright.Parent\" xml:space=\"preserve\">\n    <value>MT_About</value>\n  </data>\n  <data name=\"gb_Cluster.Text\" xml:space=\"preserve\">\n    <value>Cluster</value>\n  </data>\n  <data name=\"chb_showVDIndexOnTrayIcon.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"&gt;&gt;MT_Logs.Name\" xml:space=\"preserve\">\n    <value>MT_Logs</value>\n  </data>\n  <data name=\"&gt;&gt;rb_vd_index_0.Name\" xml:space=\"preserve\">\n    <value>rb_vd_index_0</value>\n  </data>\n  <data name=\"cb_hk_alt.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"&gt;&gt;cb_hk_win.Parent\" xml:space=\"preserve\">\n    <value>tp_hk_main</value>\n  </data>\n  <data name=\"&gt;&gt;lvc_Name.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ColumnHeader, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;gb_DesktopArrangement.Name\" xml:space=\"preserve\">\n    <value>gb_DesktopArrangement</value>\n  </data>\n  <data name=\"lb_profiles_note.Text\" xml:space=\"preserve\">\n    <value>Note: KeyBindings, MouseActions and LogConfigs are shared by all profiles. some settings may need restart to take effect.</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m3.ZOrder\" xml:space=\"preserve\">\n    <value>4</value>\n  </data>\n  <data name=\"&gt;&gt;lvc_Updated.Name\" xml:space=\"preserve\">\n    <value>lvc_Updated</value>\n  </data>\n  <data name=\"chb_showVDIndexOnTrayIcon.Text\" xml:space=\"preserve\">\n    <value>Show virtual desktop index on Tray Icon.</value>\n  </data>\n  <data name=\"cb_hk_key.Items38\" xml:space=\"preserve\">\n    <value>NumPad2</value>\n  </data>\n  <data name=\"&gt;&gt;logTabInfo.Name\" xml:space=\"preserve\">\n    <value>logTabInfo</value>\n  </data>\n  <data name=\"&gt;&gt;gb_CurrentProfile.Name\" xml:space=\"preserve\">\n    <value>gb_CurrentProfile</value>\n  </data>\n  <data name=\"btn_RuleEdit.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"lb_Copyright.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 0, 2, 0</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m4.Parent\" xml:space=\"preserve\">\n    <value>tlp_DesktopArrangement</value>\n  </data>\n  <data name=\"&gt;&gt;tbEvent.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;btn_RuleClone.Parent\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <data name=\"&gt;&gt;lb_RunOnStartup.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;logTabWarning.Parent\" xml:space=\"preserve\">\n    <value>logTabs</value>\n  </data>\n  <data name=\"lvc_PluginAuthor.Text\" xml:space=\"preserve\">\n    <value>Author</value>\n  </data>\n  <data name=\"btn_profile_rename.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>2</value>\n  </data>\n  <data name=\"&gt;&gt;btn_hk_ClearAndSave.Parent\" xml:space=\"preserve\">\n    <value>tp_hk_main</value>\n  </data>\n  <data name=\"lb_ui_vd_view.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"btn_m4.FlatStyle\" type=\"System.Windows.Forms.FlatStyle, System.Windows.Forms\">\n    <value>Flat</value>\n  </data>\n  <data name=\"tb_hk_tip.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>301, 178</value>\n  </data>\n  <data name=\"&gt;&gt;tabPage_Genernal_Main.Name\" xml:space=\"preserve\">\n    <value>tabPage_Genernal_Main</value>\n  </data>\n  <data name=\"tc_Mouse.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>434, 15</value>\n  </data>\n  <data name=\"chb_MouseOnTaskbarSwitchDesktop.Text\" xml:space=\"preserve\">\n    <value>When mouse on Taskbar, Use wheel switch virtual desktop.</value>\n  </data>\n  <data name=\"lbVersion.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>15, 122</value>\n  </data>\n  <data name=\"&gt;&gt;tabPage_Genernal_Mouse.Parent\" xml:space=\"preserve\">\n    <value>tab_General</value>\n  </data>\n  <data name=\"&gt;&gt;$this.Name\" xml:space=\"preserve\">\n    <value>AppController</value>\n  </data>\n  <data name=\"&gt;&gt;rb_vd_index_1.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.RadioButton, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"btn_m7.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n</value>\n  </data>\n  <data name=\"&gt;&gt;cb_hk_ctrl.Name\" xml:space=\"preserve\">\n    <value>cb_hk_ctrl</value>\n  </data>\n  <data name=\"btn_m5.Dock\" type=\"System.Windows.Forms.DockStyle, System.Windows.Forms\">\n    <value>Fill</value>\n  </data>\n  <data name=\"&gt;&gt;MT_Rules.ZOrder\" xml:space=\"preserve\">\n    <value>2</value>\n  </data>\n  <data name=\"&gt;&gt;cb_hk_ctrl.Parent\" xml:space=\"preserve\">\n    <value>tp_hk_main</value>\n  </data>\n  <data name=\"&gt;&gt;gb_profiles.Name\" xml:space=\"preserve\">\n    <value>gb_profiles</value>\n  </data>\n  <data name=\"lb_MouseOnTaskbarSwitchDesktop2.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>5</value>\n  </data>\n  <data name=\"&gt;&gt;panel_General.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"gb_storage.Text\" xml:space=\"preserve\">\n    <value>Storage</value>\n  </data>\n  <data name=\"btn_RuleRemove.Enabled\" type=\"System.Boolean, mscorlib\">\n    <value>False</value>\n  </data>\n  <data name=\"panel_PageNav.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"showLogsInGuiToolStripMenuItem.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>203, 22</value>\n  </data>\n  <data name=\"&gt;&gt;MT_About.Parent\" xml:space=\"preserve\">\n    <value>mainTabs</value>\n  </data>\n  <data name=\"tbDebug.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1145, 663</value>\n  </data>\n  <data name=\"&gt;&gt;lbVersion.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"gb_Cluster.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;tp_mouse_action.Parent\" xml:space=\"preserve\">\n    <value>tc_Mouse</value>\n  </data>\n  <data name=\"&gt;&gt;tc_Keyboard.Parent\" xml:space=\"preserve\">\n    <value>tabPage_Genernal_Keyboard</value>\n  </data>\n  <data name=\"btn_m3.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"gb_nav.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;tab_General.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"tsb_logs.ImageScaling\" type=\"System.Windows.Forms.ToolStripItemImageScaling, System.Windows.Forms\">\n    <value>None</value>\n  </data>\n  <data name=\"lbox_Env.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>15</value>\n  </data>\n  <data name=\"lb_AppName.Font\" type=\"System.Drawing.Font, System.Drawing\">\n    <value>Arial, 55pt</value>\n  </data>\n  <data name=\"tbWarning.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>3</value>\n  </data>\n  <data name=\"&gt;&gt;llb_goto_general.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;chb_HideOnStart.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"tsb_general.TextImageRelation\" type=\"System.Windows.Forms.TextImageRelation, System.Windows.Forms\">\n    <value>ImageAboveText</value>\n  </data>\n  <data name=\"&gt;&gt;pb_AboutLogo.ZOrder\" xml:space=\"preserve\">\n    <value>6</value>\n  </data>\n  <data name=\"&gt;&gt;cb_nav_circle_h_type.Name\" xml:space=\"preserve\">\n    <value>cb_nav_circle_h_type</value>\n  </data>\n  <data name=\"closeThisWindowToolStripMenuItem.Text\" xml:space=\"preserve\">\n    <value>Close This Window</value>\n  </data>\n  <data name=\"btn_m3.Text\" xml:space=\"preserve\">\n    <value>BottomRight to TopLeft, Horizontal</value>\n  </data>\n  <data name=\"&gt;&gt;lb_ui_vd_view.Name\" xml:space=\"preserve\">\n    <value>lb_ui_vd_view</value>\n  </data>\n  <data name=\"btn_m3.TextAlign\" type=\"System.Drawing.ContentAlignment, System.Drawing\">\n    <value>BottomCenter</value>\n  </data>\n  <data name=\"&gt;&gt;lb_Version.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"mainTabs.Dock\" type=\"System.Windows.Forms.DockStyle, System.Windows.Forms\">\n    <value>Fill</value>\n  </data>\n  <data name=\"cb_mouse_func.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>13, 46</value>\n  </data>\n  <data name=\"&gt;&gt;MT_Rules.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;panel_UI.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Panel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_hk_key.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>102, 25</value>\n  </data>\n  <data name=\"&gt;&gt;openLogFolderToolStripMenuItem.Name\" xml:space=\"preserve\">\n    <value>openLogFolderToolStripMenuItem</value>\n  </data>\n  <data name=\"&gt;&gt;rb_vdi_on_tray_style_0.Parent\" xml:space=\"preserve\">\n    <value>gb_Cluster</value>\n  </data>\n  <data name=\"tsb_general.Text\" xml:space=\"preserve\">\n    <value>General</value>\n  </data>\n  <data name=\"tp_mouse_action.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;cb_hk_ctrl.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_hk_key.Items41\" xml:space=\"preserve\">\n    <value>NumPad5</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Cluster.Parent\" xml:space=\"preserve\">\n    <value>tabPage_Genernal_Main</value>\n  </data>\n  <data name=\"panel_General.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1169, 716</value>\n  </data>\n  <data name=\"&gt;&gt;tc_Mouse.Parent\" xml:space=\"preserve\">\n    <value>tabPage_Genernal_Mouse</value>\n  </data>\n  <data name=\"cb_hk_alt.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>113, 47</value>\n  </data>\n  <data name=\"chb_show_vd_name.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>17, 28</value>\n  </data>\n  <data name=\"btn_hk_ClearAndSave.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>170, 80</value>\n  </data>\n  <data name=\"&gt;&gt;rb_vd_index_1.Name\" xml:space=\"preserve\">\n    <value>rb_vd_index_1</value>\n  </data>\n  <data name=\"rb_vd_index_0.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>74, 21</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_2.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"btn_m0.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n</value>\n  </data>\n  <data name=\"tbVerbose.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>0, 0</value>\n  </data>\n  <data name=\"lb_note_configRoot.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>2</value>\n  </data>\n  <data name=\"tabPage_Genernal_Main.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1145, 663</value>\n  </data>\n  <data name=\"&gt;&gt;logTabVerbose.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;cb_hk_win.Name\" xml:space=\"preserve\">\n    <value>cb_hk_win</value>\n  </data>\n  <data name=\"btn_PluginSettings.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAu\n        IgAALiIBquLdkgAAAbhJREFUSEut1r8rRWEcx/EzsGBgY6EkCxnIYDFJMphMpMjAoDAZDEpmi6KwKH8D\n        m2Rh8DMhKRsZWFAkOt6f7nPufTzOee653OFV3+f7fJ/zud3TOfcGQRAWUzkO8YA+08PPof+oxAlYZHWA\n        vd/Df7UBih8+0KDNOmzhvAAXuEYJopA2fMEOkRttHjnNtDah8yu4NHUL7BkjtpmXvhqdHbF626bXa/Vk\n        Wc1Xs9Cn6U6hCzqn2r6YrEJ7Y2Z9kFkH4bNp7GQaqTSBItYcNDOMqkydC9nPNPKqxRtYJBqFdaawkDLc\n        gUWiT3TCOldYyDEovNrhnEsfomeJwst6ldjShayDwmsccWeRP2QeFF4LiDtr+EOGoD2fNWh2Ev2mdvhD\n        9OxoL4nuk+Z6zHrJrB3+kD1oL84pNMNbNtubMD2HP+QK2nPdowKa0Q2P+lOm50gO0UXeoT2bnnb9PERz\n        g4j2Cg7Re0f9yBP0FbkP2wCimbwhu7lmVjUaUWr1XPbbODHkBVThGZod+mOgAP1+16Ae7swMdF6m4QRI\n        bqAYZuEESBDegqoo9KvoBEgQtkJ/DHRv/uoRi3AuLmHwDTVanr01N1gtAAAAAElFTkSuQmCC\n</value>\n  </data>\n  <data name=\"&gt;&gt;chb_RunOnStartup.Parent\" xml:space=\"preserve\">\n    <value>gb_general</value>\n  </data>\n  <data name=\"&gt;&gt;lb_AppName.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;btn_hk_RegAndSave.Parent\" xml:space=\"preserve\">\n    <value>tp_hk_main</value>\n  </data>\n  <data name=\"&gt;&gt;cb_mouse_func.Name\" xml:space=\"preserve\">\n    <value>cb_mouse_func</value>\n  </data>\n  <data name=\"&gt;&gt;chb_MouseOnTaskbarSwitchDesktop.Parent\" xml:space=\"preserve\">\n    <value>tabPage_Genernal_Mouse</value>\n  </data>\n  <data name=\"lb_mouse_action.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"chb_MouseOnTaskbarSwitchDesktop.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"cb_hk_alt.Text\" xml:space=\"preserve\">\n    <value>Alt</value>\n  </data>\n  <data name=\"&gt;&gt;cb_RuleProfiles.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;panel_UI.Name\" xml:space=\"preserve\">\n    <value>panel_UI</value>\n  </data>\n  <data name=\"lb_Copyright.Text\" xml:space=\"preserve\">\n    <value>Copyright</value>\n  </data>\n  <data name=\"btn_RuleNew.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>2</value>\n  </data>\n  <data name=\"gb_CurrentProfile.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"chb_notify_vd_changed.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"cb_hk_key.Items67\" xml:space=\"preserve\">\n    <value>PageDown</value>\n  </data>\n  <data name=\"ts_PageNav.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>3</value>\n  </data>\n  <data name=\"&gt;&gt;tv_mouse.Name\" xml:space=\"preserve\">\n    <value>tv_mouse</value>\n  </data>\n  <data name=\"gb_DesktopArrangement.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>0</value>\n  </data>\n  <data name=\"tc_Mouse.Visible\" type=\"System.Boolean, mscorlib\">\n    <value>False</value>\n  </data>\n  <data name=\"lv_Rules.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>1</value>\n  </data>\n  <data name=\"tbVerbose.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>3</value>\n  </data>\n  <data name=\"logTabError.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>4, 26</value>\n  </data>\n  <data name=\"cb_hk_shift.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>3</value>\n  </data>\n  <data name=\"&gt;&gt;cb_nav_circle_v.Parent\" xml:space=\"preserve\">\n    <value>gb_nav</value>\n  </data>\n  <data name=\"chb_notify_vd_changed.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>1</value>\n  </data>\n  <data name=\"cb_nav_circle_h.Text\" xml:space=\"preserve\">\n    <value>Enable circulation.</value>\n  </data>\n  <data name=\"&gt;&gt;lbox_Env.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ListBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"btn_RuleNew.Text\" xml:space=\"preserve\">\n    <value>    New...</value>\n  </data>\n  <data name=\"lv_Rules.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>11, 21</value>\n  </data>\n  <data name=\"btn_m7.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>830, 242</value>\n  </data>\n  <data name=\"cb_hk_key.Items16\" xml:space=\"preserve\">\n    <value>F</value>\n  </data>\n  <data name=\"optionsToolStripMenuItem.Text\" xml:space=\"preserve\">\n    <value>Options</value>\n  </data>\n  <data name=\"&gt;&gt;gb_DesktopArrangement.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"lb_Copyright.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>15, 141</value>\n  </data>\n  <data name=\"llb_TaskScheduler.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 0, 2, 0</value>\n  </data>\n  <data name=\"llb_Company.Text\" xml:space=\"preserve\">\n    <value>Company</value>\n  </data>\n  <data name=\"tsb_ui.Text\" xml:space=\"preserve\">\n    <value>UI</value>\n  </data>\n  <data name=\"btn_m0.FlatStyle\" type=\"System.Windows.Forms.FlatStyle, System.Windows.Forms\">\n    <value>Flat</value>\n  </data>\n  <data name=\"&gt;&gt;lvc_PluginEmail.Name\" xml:space=\"preserve\">\n    <value>lvc_PluginEmail</value>\n  </data>\n  <data name=\"&gt;&gt;MT_General.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"logTabDebug.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>4, 26</value>\n  </data>\n  <data name=\"MT_Logs.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>4, 26</value>\n  </data>\n  <data name=\"&gt;&gt;chb_show_vd_name.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"btn_profile_del.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>598, 25</value>\n  </data>\n  <data name=\"gb_CurrentProfile.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1137, 59</value>\n  </data>\n  <data name=\"&gt;&gt;btn_chooseConfigRoot.Parent\" xml:space=\"preserve\">\n    <value>gb_storage</value>\n  </data>\n  <data name=\"cb_nav_circle_v.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"&gt;&gt;lvc_PluginEmail.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ColumnHeader, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"tv_keyboard.Nodes2\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n    <value>\n        AAEAAAD/////AQAAAAAAAAAMAgAAAEZTeXN0ZW0uV2luZG93cy5Gb3JtcywgQ3VsdHVyZT1uZXV0cmFs\n        LCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAdU3lzdGVtLldpbmRvd3MuRm9ybXMu\n        VHJlZU5vZGULAAAABFRleHQLVG9vbFRpcFRleHQETmFtZQlJc0NoZWNrZWQKSW1hZ2VJbmRleAhJbWFn\n        ZUtleRJTZWxlY3RlZEltYWdlSW5kZXgQU2VsZWN0ZWRJbWFnZUtleQpDaGlsZENvdW50CWNoaWxkcmVu\n        MAljaGlsZHJlbjEBAQEAAAEAAQAEBAEICAgdU3lzdGVtLldpbmRvd3MuRm9ybXMuVHJlZU5vZGUCAAAA\n        HVN5c3RlbS5XaW5kb3dzLkZvcm1zLlRyZWVOb2RlAgAAAAIAAAAGAwAAAAZXaW5kb3cGBAAAAAAGBQAA\n        AA5oa19yb290X3dpbmRvdwD/////CQQAAAD/////CQQAAAACAAAACQcAAAAJCAAAAAUHAAAAHVN5c3Rl\n        bS5XaW5kb3dzLkZvcm1zLlRyZWVOb2RlCQAAAARUZXh0C1Rvb2xUaXBUZXh0BE5hbWUJSXNDaGVja2Vk\n        CkltYWdlSW5kZXgISW1hZ2VLZXkSU2VsZWN0ZWRJbWFnZUluZGV4EFNlbGVjdGVkSW1hZ2VLZXkKQ2hp\n        bGRDb3VudAEBAQAAAQABAAEICAgCAAAABgkAAAAETW92ZQkEAAAABgsAAAASaGtfcGFyZW50X3dpbl9t\n        b3ZlAP////8JBAAAAP////8JBAAAAAAAAAAFCAAAAB1TeXN0ZW0uV2luZG93cy5Gb3Jtcy5UcmVlTm9k\n        ZQkAAAAEVGV4dAtUb29sVGlwVGV4dAROYW1lCUlzQ2hlY2tlZApJbWFnZUluZGV4CEltYWdlS2V5ElNl\n        bGVjdGVkSW1hZ2VJbmRleBBTZWxlY3RlZEltYWdlS2V5CkNoaWxkQ291bnQBAQEAAAEAAQABCAgIAgAA\n        AAYNAAAAD01vdmUgYW5kIEZvbGxvdwkEAAAABg8AAAAZaGtfcGFyZW50X3dpbl9tb3ZlX2ZvbGxvdwD/\n        ////CQQAAAD/////CQQAAAAAAAAACw==\n</value>\n  </data>\n  <data name=\"&gt;&gt;clearToolStripMenuItem.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"MT_Plugins.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1169, 716</value>\n  </data>\n  <data name=\"mainTabs.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1177, 746</value>\n  </data>\n  <data name=\"lb_hk_extra.Font\" type=\"System.Drawing.Font, System.Drawing\">\n    <value>Microsoft YaHei UI, 9pt, style=Bold</value>\n  </data>\n  <data name=\"&gt;&gt;lb_hk_extra.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"btn_RuleNew.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"chb_RunOnStartup.Text\" xml:space=\"preserve\">\n    <value>Launch program at system startup.</value>\n  </data>\n  <data name=\"cb_hk_key.Items60\" xml:space=\"preserve\">\n    <value>Right</value>\n  </data>\n  <data name=\"btn_m1.Dock\" type=\"System.Windows.Forms.DockStyle, System.Windows.Forms\">\n    <value>Fill</value>\n  </data>\n  <data name=\"&gt;&gt;cb_hk_key.Parent\" xml:space=\"preserve\">\n    <value>tp_hk_main</value>\n  </data>\n  <data name=\"chb_MouseOnTaskbarSwitchDesktop.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>498, 20</value>\n  </data>\n  <data name=\"chb_show_vd_index.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;rb_vd_index_0.Parent\" xml:space=\"preserve\">\n    <value>lb_ui_vd_view</value>\n  </data>\n  <data name=\"lb_note_configRoot.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>22, 54</value>\n  </data>\n  <data name=\"&gt;&gt;tsmiMainMenuQuit.Name\" xml:space=\"preserve\">\n    <value>tsmiMainMenuQuit</value>\n  </data>\n  <data name=\"cb_hk_key.Items46\" xml:space=\"preserve\">\n    <value>NumPad0</value>\n  </data>\n  <data name=\"&gt;&gt;tp_hk_extra.Name\" xml:space=\"preserve\">\n    <value>tp_hk_extra</value>\n  </data>\n  <data name=\"&gt;&gt;cb_hk_key.Name\" xml:space=\"preserve\">\n    <value>cb_hk_key</value>\n  </data>\n  <data name=\"tv_keyboard.Nodes\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n    <value>\n        AAEAAAD/////AQAAAAAAAAAMAgAAAEZTeXN0ZW0uV2luZG93cy5Gb3JtcywgQ3VsdHVyZT1uZXV0cmFs\n        LCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAdU3lzdGVtLldpbmRvd3MuRm9ybXMu\n        VHJlZU5vZGUOAAAABFRleHQLVG9vbFRpcFRleHQETmFtZQlJc0NoZWNrZWQKSW1hZ2VJbmRleAhJbWFn\n        ZUtleRJTZWxlY3RlZEltYWdlSW5kZXgQU2VsZWN0ZWRJbWFnZUtleQpDaGlsZENvdW50CWNoaWxkcmVu\n        MAljaGlsZHJlbjEJY2hpbGRyZW4yCWNoaWxkcmVuMwljaGlsZHJlbjQBAQEAAAEAAQAEBAQEBAEICAgd\n        U3lzdGVtLldpbmRvd3MuRm9ybXMuVHJlZU5vZGUCAAAAHVN5c3RlbS5XaW5kb3dzLkZvcm1zLlRyZWVO\n        b2RlAgAAAB1TeXN0ZW0uV2luZG93cy5Gb3Jtcy5UcmVlTm9kZQIAAAAdU3lzdGVtLldpbmRvd3MuRm9y\n        bXMuVHJlZU5vZGUCAAAAHVN5c3RlbS5XaW5kb3dzLkZvcm1zLlRyZWVOb2RlAgAAAAIAAAAGAwAAAAdH\n        ZW5lcmFsBgQAAAAABgUAAAAPaGtfcm9vdF9nZW5lcmFsAP////8JBAAAAP////8JBAAAAAUAAAAJBwAA\n        AAkIAAAACQkAAAAJCgAAAAkLAAAABQcAAAAdU3lzdGVtLldpbmRvd3MuRm9ybXMuVHJlZU5vZGUJAAAA\n        BFRleHQLVG9vbFRpcFRleHQETmFtZQlJc0NoZWNrZWQKSW1hZ2VJbmRleAhJbWFnZUtleRJTZWxlY3Rl\n        ZEltYWdlSW5kZXgQU2VsZWN0ZWRJbWFnZUtleQpDaGlsZENvdW50AQEBAAABAAEAAQgICAIAAAAGDAAA\n        AA1SaXNlIE1haW5WaWV3CQQAAAAGDgAAABVoa19ub2RlX3Jpc2VfbWFpbnZpZXcA/////wkEAAAA////\n        /wkEAAAAAAAAAAUIAAAAHVN5c3RlbS5XaW5kb3dzLkZvcm1zLlRyZWVOb2RlCQAAAARUZXh0C1Rvb2xU\n        aXBUZXh0BE5hbWUJSXNDaGVja2VkCkltYWdlSW5kZXgISW1hZ2VLZXkSU2VsZWN0ZWRJbWFnZUluZGV4\n        EFNlbGVjdGVkSW1hZ2VLZXkKQ2hpbGRDb3VudAEBAQAAAQABAAEICAgCAAAABhAAAAAST3BlbiBBcHBD\n        b250cm9sbGVyCQQAAAAGEgAAABtoa19ub2RlX29wZW5fYXBwX2NvbnRyb2xsZXIA/////wkEAAAA////\n        /wkEAAAAAAAAAAUJAAAAHVN5c3RlbS5XaW5kb3dzLkZvcm1zLlRyZWVOb2RlCQAAAARUZXh0C1Rvb2xU\n        aXBUZXh0BE5hbWUJSXNDaGVja2VkCkltYWdlSW5kZXgISW1hZ2VLZXkSU2VsZWN0ZWRJbWFnZUluZGV4\n        EFNlbGVjdGVkSW1hZ2VLZXkKQ2hpbGRDb3VudAEBAQAAAQABAAEICAgCAAAABhQAAAAcUmlzZSBNYWlu\n        VmlldyBGb3IgQWN0aXZlIEFwcAkEAAAABhYAAAAkaGtfbm9kZV9yaXNlX21haW52aWV3X2Zvcl9hY3Rp\n        dmVfYXBwAP////8JBAAAAP////8JBAAAAAAAAAAFCgAAAB1TeXN0ZW0uV2luZG93cy5Gb3Jtcy5UcmVl\n        Tm9kZQkAAAAEVGV4dAtUb29sVGlwVGV4dAROYW1lCUlzQ2hlY2tlZApJbWFnZUluZGV4CEltYWdlS2V5\n        ElNlbGVjdGVkSW1hZ2VJbmRleBBTZWxlY3RlZEltYWdlS2V5CkNoaWxkQ291bnQBAQEAAAEAAQABCAgI\n        AgAAAAYYAAAAIVJpc2UgTWFpblZpZXcgRm9yIEN1cnJlbnQgRGVza3RvcAkEAAAABhoAAAAkaGtfbm9k\n        ZV9yaXNlX21haW52aWV3X2Zvcl9jdXJyZW50X3ZkAP////8JBAAAAP////8JBAAAAAAAAAAFCwAAAB1T\n        eXN0ZW0uV2luZG93cy5Gb3Jtcy5UcmVlTm9kZQkAAAAEVGV4dAtUb29sVGlwVGV4dAROYW1lCUlzQ2hl\n        Y2tlZApJbWFnZUluZGV4CEltYWdlS2V5ElNlbGVjdGVkSW1hZ2VJbmRleBBTZWxlY3RlZEltYWdlS2V5\n        CkNoaWxkQ291bnQBAQEAAAEAAQABCAgIAgAAAAYcAAAAN1Jpc2UgTWFpblZpZXcgRm9yIEFjdGl2ZSBB\n        cHAgSW4gQ3VycmVudCBWaXJ0dWFsIERlc2t0b3AJBAAAAAYeAAAAMmhrX25vZGVfcmlzZV9tYWludmll\n        d19mb3JfYWN0aXZlX2FwcF9pbl9jdXJyZW50X3ZkAP////8JBAAAAP////8JBAAAAAAAAAAL\n</value>\n  </data>\n  <data name=\"&gt;&gt;lb_MouseOnTaskbarSwitchDesktop2.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"tabPage_Genernal_Keyboard.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>3, 3, 3, 3</value>\n  </data>\n  <data name=\"&gt;&gt;chb_HideOnStart.ZOrder\" xml:space=\"preserve\">\n    <value>3</value>\n  </data>\n  <data name=\"cb_nav_circle_v.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>1</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m3.Name\" xml:space=\"preserve\">\n    <value>btn_m3</value>\n  </data>\n  <data name=\"lvc_PluginVersion.TextAlign\" type=\"System.Windows.Forms.HorizontalAlignment, System.Windows.Forms\">\n    <value>Right</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_profiles.ZOrder\" xml:space=\"preserve\">\n    <value>4</value>\n  </data>\n  <data name=\"logTabDebug.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>0</value>\n  </data>\n  <data name=\"MT_UI.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>2</value>\n  </data>\n  <data name=\"&gt;&gt;lvc_PluginAuthor.Name\" xml:space=\"preserve\">\n    <value>lvc_PluginAuthor</value>\n  </data>\n  <data name=\"btn_m7.FlatStyle\" type=\"System.Windows.Forms.FlatStyle, System.Windows.Forms\">\n    <value>Flat</value>\n  </data>\n  <data name=\"&gt;&gt;tabPage_Genernal_Main.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;logTabInfo.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"tabPage_Genernal_Main.Text\" xml:space=\"preserve\">\n    <value>Main</value>\n  </data>\n  <data name=\"gb_nav.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>10, 119</value>\n  </data>\n  <data name=\"lb_ui_vd_view.Text\" xml:space=\"preserve\">\n    <value>Virtual Desktop View</value>\n  </data>\n  <data name=\"chb_notify_vd_changed.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>498, 20</value>\n  </data>\n  <data name=\"&gt;&gt;lb_mouse_action.Parent\" xml:space=\"preserve\">\n    <value>tp_mouse_action</value>\n  </data>\n  <data name=\"lb_hk_func.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>12, 18</value>\n  </data>\n  <data name=\"logTabEvent.Text\" xml:space=\"preserve\">\n    <value>Event</value>\n  </data>\n  <data name=\"tp_hk_main.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"cb_hk_ctrl.Text\" xml:space=\"preserve\">\n    <value>Ctrl</value>\n  </data>\n  <data name=\"&gt;&gt;logTabs.Name\" xml:space=\"preserve\">\n    <value>logTabs</value>\n  </data>\n  <data name=\"&gt;&gt;lvc_Created.Name\" xml:space=\"preserve\">\n    <value>lvc_Created</value>\n  </data>\n  <data name=\"btn_profile_rename.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>101, 25</value>\n  </data>\n  <data name=\"rb_vd_index_1.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>3</value>\n  </data>\n  <data name=\"lvc_PluginEmail.Width\" type=\"System.Int32, mscorlib\">\n    <value>300</value>\n  </data>\n  <data name=\"chb_show_vd_index.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"btn_profile_rename.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"&gt;&gt;tbDebug.Parent\" xml:space=\"preserve\">\n    <value>logTabDebug</value>\n  </data>\n  <data name=\"&gt;&gt;tbWarning.Name\" xml:space=\"preserve\">\n    <value>tbWarning</value>\n  </data>\n  <data name=\"tabPage_Genernal_Main.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>3, 3, 3, 3</value>\n  </data>\n  <data name=\"toolStripSeparator1.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>199, 6</value>\n  </data>\n  <data name=\"MT_About.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"cb_nav_circle_v.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>22, 59</value>\n  </data>\n  <data name=\"lb_configRoot.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>6</value>\n  </data>\n  <data name=\"&gt;&gt;lv_Rules.Parent\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <data name=\"llb_Company.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>15, 161</value>\n  </data>\n  <data name=\"&gt;&gt;tsb_ui.Name\" xml:space=\"preserve\">\n    <value>tsb_ui</value>\n  </data>\n  <data name=\"logTabInfo.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>1</value>\n  </data>\n  <data name=\"helpToolStripMenuItem.Text\" xml:space=\"preserve\">\n    <value>Help</value>\n  </data>\n  <data name=\"&gt;&gt;btn_RuleRemove.Parent\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <data name=\"&gt;&gt;panel_mask.Name\" xml:space=\"preserve\">\n    <value>panel_mask</value>\n  </data>\n  <data name=\"chb_show_vd_index.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>17, 58</value>\n  </data>\n  <data name=\"MT_Plugins.Text\" xml:space=\"preserve\">\n    <value>Plugins</value>\n  </data>\n  <data name=\"&gt;&gt;tlp_DesktopArrangement.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"btn_RuleEdit.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>6, 0, 0, 0</value>\n  </data>\n  <data name=\"tp_hk_main.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>492, 470</value>\n  </data>\n  <data name=\"&gt;&gt;tb_hk_tip.ZOrder\" xml:space=\"preserve\">\n    <value>2</value>\n  </data>\n  <data name=\"&gt;&gt;MT_Plugins.Name\" xml:space=\"preserve\">\n    <value>MT_Plugins</value>\n  </data>\n  <data name=\"gb_profiles.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>10, 516</value>\n  </data>\n  <data name=\"tsb_logs.ImageTransparentColor\" type=\"System.Drawing.Color, System.Drawing\">\n    <value>Magenta</value>\n  </data>\n  <data name=\"btn_m6.Text\" xml:space=\"preserve\">\n    <value>BottomLeft to TopRight, Vertical</value>\n  </data>\n  <data name=\"btn_m1.Text\" xml:space=\"preserve\">\n    <value>TopRight to BottomLeft, Horizontal</value>\n  </data>\n  <data name=\"&gt;&gt;langToolStripMenuItem.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;chb_HideMainViewIfItsShown.Name\" xml:space=\"preserve\">\n    <value>chb_HideMainViewIfItsShown</value>\n  </data>\n  <data name=\"gb_general.Text\" xml:space=\"preserve\">\n    <value>General</value>\n  </data>\n  <data name=\"tb_hk_tip.Enabled\" type=\"System.Boolean, mscorlib\">\n    <value>False</value>\n  </data>\n  <data name=\"gb_DesktopArrangement.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m0.ZOrder\" xml:space=\"preserve\">\n    <value>7</value>\n  </data>\n  <data name=\"btn_profile_del.Text\" xml:space=\"preserve\">\n    <value>Delete...</value>\n  </data>\n  <data name=\"gb_Plugins.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>11, 14</value>\n  </data>\n  <data name=\"tsb_plugins.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n</value>\n  </data>\n  <data name=\"logTabWarning.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>4, 26</value>\n  </data>\n  <data name=\"&gt;&gt;langToolStripMenuItem.Name\" xml:space=\"preserve\">\n    <value>langToolStripMenuItem</value>\n  </data>\n  <data name=\"lvc_PluginName.Text\" xml:space=\"preserve\">\n    <value>Name</value>\n  </data>\n  <data name=\"&gt;&gt;tsb_plugins.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStripButton, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"tv_mouse.Nodes\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n    <value>\n        AAEAAAD/////AQAAAAAAAAAMAgAAAEZTeXN0ZW0uV2luZG93cy5Gb3JtcywgQ3VsdHVyZT1uZXV0cmFs\n        LCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAdU3lzdGVtLldpbmRvd3MuRm9ybXMu\n        VHJlZU5vZGULAAAABFRleHQLVG9vbFRpcFRleHQETmFtZQlJc0NoZWNrZWQKSW1hZ2VJbmRleAhJbWFn\n        ZUtleRJTZWxlY3RlZEltYWdlSW5kZXgQU2VsZWN0ZWRJbWFnZUtleQpDaGlsZENvdW50CWNoaWxkcmVu\n        MAljaGlsZHJlbjEBAQEAAAEAAQAEBAEICAgdU3lzdGVtLldpbmRvd3MuRm9ybXMuVHJlZU5vZGUCAAAA\n        HVN5c3RlbS5XaW5kb3dzLkZvcm1zLlRyZWVOb2RlAgAAAAIAAAAGAwAAAAhNYWluVmlldwYEAAAAAAYF\n        AAAAE21vdXNlX3Jvb3RfbWFpbnZpZXcA/////wkEAAAA/////wkEAAAAAgAAAAkHAAAACQgAAAAFBwAA\n        AB1TeXN0ZW0uV2luZG93cy5Gb3Jtcy5UcmVlTm9kZQkAAAAEVGV4dAtUb29sVGlwVGV4dAROYW1lCUlz\n        Q2hlY2tlZApJbWFnZUluZGV4CEltYWdlS2V5ElNlbGVjdGVkSW1hZ2VJbmRleBBTZWxlY3RlZEltYWdl\n        S2V5CkNoaWxkQ291bnQBAQEAAAEAAQABCAgIAgAAAAYJAAAAB0Rlc2t0b3AJBAAAAAYLAAAAFG1vdXNl\n        X3BhcmVudF9kZXNrdG9wAP////8JBAAAAP////8JBAAAAAAAAAAFCAAAAB1TeXN0ZW0uV2luZG93cy5G\n        b3Jtcy5UcmVlTm9kZQkAAAAEVGV4dAtUb29sVGlwVGV4dAROYW1lCUlzQ2hlY2tlZApJbWFnZUluZGV4\n        CEltYWdlS2V5ElNlbGVjdGVkSW1hZ2VJbmRleBBTZWxlY3RlZEltYWdlS2V5CkNoaWxkQ291bnQBAQEA\n        AAEAAQABCAgIAgAAAAYNAAAABldpbmRvdwkEAAAABg8AAAATbW91c2VfcGFyZW50X3dpbmRvdwD/////\n        CQQAAAD/////CQQAAAAAAAAACw==\n</value>\n  </data>\n  <data name=\"lb_hk_extra.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 0, 2, 0</value>\n  </data>\n  <data name=\"&gt;&gt;cb_hk_key.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"tp_mouse_action.Text\" xml:space=\"preserve\">\n    <value>Action</value>\n  </data>\n  <data name=\"btn_mouse_save.Text\" xml:space=\"preserve\">\n    <value>Save</value>\n  </data>\n  <data name=\"logTabVerbose.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>4, 26</value>\n  </data>\n  <data name=\"gb_general.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;lb_hk_extra.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"tv_mouse.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>10, 15</value>\n  </data>\n  <data name=\"gb_Plugins.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"tv_keyboard.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>0</value>\n  </data>\n  <data name=\"btn_m6.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"tv_keyboard.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>420, 500</value>\n  </data>\n  <data name=\"tb_hk_tip.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>12, 124</value>\n  </data>\n  <data name=\"chb_MouseOnTaskbarSwitchDesktop.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>3</value>\n  </data>\n  <data name=\"gb_nav.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>0</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_1.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"&gt;&gt;lb_nav_circle_h_type.Parent\" xml:space=\"preserve\">\n    <value>gb_nav</value>\n  </data>\n  <data name=\"&gt;&gt;logTabs.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"cb_hk_key.Items13\" xml:space=\"preserve\">\n    <value>C</value>\n  </data>\n  <data name=\"&gt;&gt;MT_About.Name\" xml:space=\"preserve\">\n    <value>MT_About</value>\n  </data>\n  <data name=\"tbError.ScrollBars\" type=\"System.Windows.Forms.ScrollBars, System.Windows.Forms\">\n    <value>Vertical</value>\n  </data>\n  <data name=\"&gt;&gt;lb_configRoot.Parent\" xml:space=\"preserve\">\n    <value>gb_storage</value>\n  </data>\n  <data name=\"btn_hk_ClearAndSave.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>143, 36</value>\n  </data>\n  <data name=\"btn_chooseConfigRoot.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>5</value>\n  </data>\n  <data name=\"btn_m1.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_2.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"fileToolStripMenuItem.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>39, 21</value>\n  </data>\n  <data name=\"&gt;&gt;btn_RuleEdit.Name\" xml:space=\"preserve\">\n    <value>btn_RuleEdit</value>\n  </data>\n  <data name=\"MT_UI.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>4, 26</value>\n  </data>\n  <data name=\"gb_CurrentProfile.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>11, 14</value>\n  </data>\n  <data name=\"&gt;&gt;tabPage_Genernal_Mouse.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"logTabError.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>3</value>\n  </data>\n  <data name=\"lbVersion.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 0, 2, 0</value>\n  </data>\n  <data name=\"cb_hk_key.Items49\" xml:space=\"preserve\">\n    <value>F3</value>\n  </data>\n  <data name=\"&gt;&gt;btn_profile_del.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"&gt;&gt;rb_vd_index_0.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.RadioButton, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;rb_vdi_on_tray_style_2.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.RadioButton, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;lb_Version.ZOrder\" xml:space=\"preserve\">\n    <value>4</value>\n  </data>\n  <data name=\"llb_goto_general.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>1</value>\n  </data>\n  <data name=\"btn_profile_rename.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>491, 25</value>\n  </data>\n  <data name=\"cb_hk_key.Items11\" xml:space=\"preserve\">\n    <value>A</value>\n  </data>\n  <data name=\"btn_m0.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"llb_TaskScheduler.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>350, 59</value>\n  </data>\n  <data name=\"aboutToolStripMenuItem.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>111, 22</value>\n  </data>\n  <data name=\"btn_m3.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>272, 236</value>\n  </data>\n  <data name=\"btn_RuleEdit.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>95, 40</value>\n  </data>\n  <data name=\"btn_m5.FlatStyle\" type=\"System.Windows.Forms.FlatStyle, System.Windows.Forms\">\n    <value>Flat</value>\n  </data>\n  <data name=\"rb_vd_index_0.Text\" xml:space=\"preserve\">\n    <value>0-based</value>\n  </data>\n  <data name=\"tbVerbose.Dock\" type=\"System.Windows.Forms.DockStyle, System.Windows.Forms\">\n    <value>Fill</value>\n  </data>\n  <data name=\"&gt;&gt;MT_Plugins.ZOrder\" xml:space=\"preserve\">\n    <value>3</value>\n  </data>\n  <data name=\"lvc_Name.Text\" xml:space=\"preserve\">\n    <value>Name</value>\n  </data>\n  <data name=\"chb_showVDIndexOnTrayIcon.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>409, 20</value>\n  </data>\n  <data name=\"&gt;&gt;lb_profiles_note.Name\" xml:space=\"preserve\">\n    <value>lb_profiles_note</value>\n  </data>\n  <data name=\"&gt;&gt;rb_vdi_on_tray_style_0.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.RadioButton, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;pb_AboutLogo.Name\" xml:space=\"preserve\">\n    <value>pb_AboutLogo</value>\n  </data>\n  <data name=\"&gt;&gt;btn_hk_RegAndSave.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"btn_PluginSettings.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>95, 40</value>\n  </data>\n  <data name=\"tsb_plugins.TextImageRelation\" type=\"System.Windows.Forms.TextImageRelation, System.Windows.Forms\">\n    <value>ImageAboveText</value>\n  </data>\n  <data name=\"gb_Plugins.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>8</value>\n  </data>\n  <data name=\"btn_profile_del.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"chb_showVDIndexOnTrayIcon.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>5</value>\n  </data>\n  <data name=\"&gt;&gt;gb_CurrentProfile.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;btn_chooseConfigRoot.Name\" xml:space=\"preserve\">\n    <value>btn_chooseConfigRoot</value>\n  </data>\n  <data name=\"lvc_Name.Width\" type=\"System.Int32, mscorlib\">\n    <value>600</value>\n  </data>\n  <data name=\"&gt;&gt;logTabEvent.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"$this.ClientSize\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1291, 810</value>\n  </data>\n  <data name=\"llb_TaskScheduler.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"MT_UI.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1169, 716</value>\n  </data>\n  <data name=\"&gt;&gt;chb_show_vd_index.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;btn_profile_del.Name\" xml:space=\"preserve\">\n    <value>btn_profile_del</value>\n  </data>\n  <data name=\"tabPage_Genernal_Mouse.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>4, 26</value>\n  </data>\n  <data name=\"chb_HideMainViewIfItsShown.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>498, 20</value>\n  </data>\n  <data name=\"&gt;&gt;tc_Keyboard.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Plugins.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;btn_profile_rename.Name\" xml:space=\"preserve\">\n    <value>btn_profile_rename</value>\n  </data>\n  <data name=\"ts_PageNav.Text\" xml:space=\"preserve\">\n    <value>toolStrip1</value>\n  </data>\n  <data name=\"lb_note_configRoot.Text\" xml:space=\"preserve\">\n    <value>Note: change config folder need restart program. this operation only change location, no files will be copied or moved to avoid overwrite files unexpectedly. if you want reuse current configs, you may manually copy 'settings.json' and 'Profiles' to the folder you choosed, then restart program.</value>\n  </data>\n  <data name=\"cb_hk_key.Items1\" xml:space=\"preserve\">\n    <value>D1</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Plugins.Name\" xml:space=\"preserve\">\n    <value>gb_Plugins</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_0.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"panel_General.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>0, 0</value>\n  </data>\n  <data name=\"btn_m2.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>554, 2</value>\n  </data>\n  <data name=\"&gt;&gt;lb_DesktopArrangementNote.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"logTabInfo.Text\" xml:space=\"preserve\">\n    <value>Info</value>\n  </data>\n  <data name=\"&gt;&gt;btn_RuleRemove.Name\" xml:space=\"preserve\">\n    <value>btn_RuleRemove</value>\n  </data>\n  <data name=\"btn_mouse_save.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>463, 35</value>\n  </data>\n  <data name=\"&gt;&gt;lb_configRoot.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"chb_HideOnStart.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;cb_nav_circle_h.Parent\" xml:space=\"preserve\">\n    <value>gb_nav</value>\n  </data>\n  <data name=\"&gt;&gt;logTabError.Name\" xml:space=\"preserve\">\n    <value>logTabError</value>\n  </data>\n  <data name=\"lvc_Created.TextAlign\" type=\"System.Windows.Forms.HorizontalAlignment, System.Windows.Forms\">\n    <value>Right</value>\n  </data>\n  <data name=\"cb_hk_key.Items40\" xml:space=\"preserve\">\n    <value>NumPad4</value>\n  </data>\n  <data name=\"cb_nav_circle_h_type.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>2</value>\n  </data>\n  <data name=\"llb_Company.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>16</value>\n  </data>\n  <data name=\"&gt;&gt;tbVerbose.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;cb_mouse_func.Parent\" xml:space=\"preserve\">\n    <value>tp_mouse_action</value>\n  </data>\n  <data name=\"cb_hk_alt.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>2</value>\n  </data>\n  <data name=\"lb_DesktopArrangementNote.Text\" xml:space=\"preserve\">\n    <value>Note: If and only when the number of virtual desktops is the power of 2 of the natural number [1,n], the arrangement can be changed; if the conditions are not satisfied, the program will automatically reset to the first arrangement.</value>\n  </data>\n  <data name=\"lb_Version.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>74, 122</value>\n  </data>\n  <data name=\"lb_DesktopArrangementNote.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>15, 525</value>\n  </data>\n  <data name=\"&gt;&gt;logTabError.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;lb_MouseOnTaskbarSwitchDesktop2.Parent\" xml:space=\"preserve\">\n    <value>tabPage_Genernal_Mouse</value>\n  </data>\n  <data name=\"&gt;&gt;optionsToolStripMenuItem.Name\" xml:space=\"preserve\">\n    <value>optionsToolStripMenuItem</value>\n  </data>\n  <data name=\"tsb_ui.ImageTransparentColor\" type=\"System.Drawing.Color, System.Drawing\">\n    <value>Magenta</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_0.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>453, 76</value>\n  </data>\n  <data name=\"lb_MouseOnTaskbarSwitchDesktop1.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>121, 551</value>\n  </data>\n  <data name=\"btn_m6.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>6</value>\n  </data>\n  <data name=\"&gt;&gt;llb_TaskScheduler.Name\" xml:space=\"preserve\">\n    <value>llb_TaskScheduler</value>\n  </data>\n  <data name=\"lb_hk_func.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>85, 17</value>\n  </data>\n  <data name=\"btn_PluginSettings.Enabled\" type=\"System.Boolean, mscorlib\">\n    <value>False</value>\n  </data>\n  <data name=\"panel_mask.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"cb_hk_key.Items25\" xml:space=\"preserve\">\n    <value>O</value>\n  </data>\n  <data name=\"&gt;&gt;chb_HideMainViewIfItsShown.Parent\" xml:space=\"preserve\">\n    <value>gb_Cluster</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m6.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"&gt;&gt;logTabDebug.Name\" xml:space=\"preserve\">\n    <value>logTabDebug</value>\n  </data>\n  <data name=\"gb_storage.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;tlp_DesktopArrangement.Name\" xml:space=\"preserve\">\n    <value>tlp_DesktopArrangement</value>\n  </data>\n  <data name=\"&gt;&gt;lb_ui_vd_view.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;tsb_ui.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStripButton, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;lb_AppName.Parent\" xml:space=\"preserve\">\n    <value>MT_About</value>\n  </data>\n  <data name=\"btn_m6.TextAlign\" type=\"System.Drawing.ContentAlignment, System.Drawing\">\n    <value>BottomCenter</value>\n  </data>\n  <data name=\"&gt;&gt;lv_Plugins.Name\" xml:space=\"preserve\">\n    <value>lv_Plugins</value>\n  </data>\n  <data name=\"gb_storage.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>10, 382</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Rules.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"MT_Logs.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;cb_nav_circle_h.Name\" xml:space=\"preserve\">\n    <value>cb_nav_circle_h</value>\n  </data>\n  <data name=\"gb_Plugins.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;cb_nav_circle_v.Name\" xml:space=\"preserve\">\n    <value>cb_nav_circle_v</value>\n  </data>\n  <data name=\"cb_hk_key.Items61\" xml:space=\"preserve\">\n    <value>Up</value>\n  </data>\n  <data name=\"lbox_Env.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;chb_notify_vd_changed.Parent\" xml:space=\"preserve\">\n    <value>gb_Cluster</value>\n  </data>\n  <data name=\"tb_configRoot.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>4</value>\n  </data>\n  <data name=\"langToolStripMenuItem.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>139, 22</value>\n  </data>\n  <data name=\"tbEvent.Dock\" type=\"System.Windows.Forms.DockStyle, System.Windows.Forms\">\n    <value>Fill</value>\n  </data>\n  <data name=\"logTabs.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1153, 693</value>\n  </data>\n  <data name=\"gb_nav.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>778, 95</value>\n  </data>\n  <data name=\"MT_Logs.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>1</value>\n  </data>\n  <data name=\"&gt;&gt;fileToolStripMenuItem.Name\" xml:space=\"preserve\">\n    <value>fileToolStripMenuItem</value>\n  </data>\n  <data name=\"tsb_rules.Text\" xml:space=\"preserve\">\n    <value>Rules</value>\n  </data>\n  <data name=\"mainStatusStrip.Text\" xml:space=\"preserve\">\n    <value>statusStrip1</value>\n  </data>\n  <data name=\"panel_UI.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>0, 0, 0, 0</value>\n  </data>\n  <data name=\"chb_show_vd_name.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"tp_hk_extra.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"chb_show_vd_name.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;lb_RunOnStartup.Parent\" xml:space=\"preserve\">\n    <value>gb_general</value>\n  </data>\n  <data name=\"tbInfo.Multiline\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"cb_hk_key.Items33\" xml:space=\"preserve\">\n    <value>W</value>\n  </data>\n  <data name=\"btn_m0.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;lb_DesktopArrangementNote.Parent\" xml:space=\"preserve\">\n    <value>gb_DesktopArrangement</value>\n  </data>\n  <data name=\"tsb_plugins.ImageScaling\" type=\"System.Windows.Forms.ToolStripItemImageScaling, System.Windows.Forms\">\n    <value>None</value>\n  </data>\n  <data name=\"lvc_Updated.Text\" xml:space=\"preserve\">\n    <value>Updated</value>\n  </data>\n  <data name=\"&gt;&gt;tbDebug.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"panel_General.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>1</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m1.ZOrder\" xml:space=\"preserve\">\n    <value>6</value>\n  </data>\n  <data name=\"tv_mouse.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;lb_ui_vd_view.Parent\" xml:space=\"preserve\">\n    <value>panel_UI</value>\n  </data>\n  <data name=\"btn_RuleRemove.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>95, 40</value>\n  </data>\n  <data name=\"btn_mouse_save.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>8</value>\n  </data>\n  <data name=\"lv_Plugins.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>11, 21</value>\n  </data>\n  <data name=\"tab_General.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>6</value>\n  </data>\n  <data name=\"btn_PluginSettings.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>6, 0, 0, 0</value>\n  </data>\n  <data name=\"&gt;&gt;tv_mouse.Parent\" xml:space=\"preserve\">\n    <value>tabPage_Genernal_Mouse</value>\n  </data>\n  <data name=\"cb_hk_key.Items52\" xml:space=\"preserve\">\n    <value>F6</value>\n  </data>\n  <data name=\"&gt;&gt;gb_profiles.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;cb_mouse_func.ZOrder\" xml:space=\"preserve\">\n    <value>2</value>\n  </data>\n  <data name=\"tc_Keyboard.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>500, 500</value>\n  </data>\n  <data name=\"panel_General.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>0, 0, 0, 0</value>\n  </data>\n  <data name=\"logTabEvent.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>4</value>\n  </data>\n  <data name=\"lb_nav_circle_h_type.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"cb_hk_key.Items35\" xml:space=\"preserve\">\n    <value>Y</value>\n  </data>\n  <data name=\"btn_RuleEdit.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"cb_mouse_func.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>464, 25</value>\n  </data>\n  <data name=\"btn_m1.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n</value>\n  </data>\n  <data name=\"panel_Pages.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"tsb_rules.ImageTransparentColor\" type=\"System.Drawing.Color, System.Drawing\">\n    <value>Magenta</value>\n  </data>\n  <data name=\"&gt;&gt;chb_MouseOnTaskbarSwitchDesktop.Name\" xml:space=\"preserve\">\n    <value>chb_MouseOnTaskbarSwitchDesktop</value>\n  </data>\n  <data name=\"btn_m5.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>272, 236</value>\n  </data>\n  <data name=\"&gt;&gt;tabPage_Genernal_Keyboard.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"cb_hk_key.Items59\" xml:space=\"preserve\">\n    <value>Left</value>\n  </data>\n  <data name=\"&gt;&gt;btn_PluginSettings.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"panel_mask.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>5</value>\n  </data>\n  <data name=\"cb_nav_circle_h.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>0</value>\n  </data>\n  <data name=\"cb_hk_key.Items30\" xml:space=\"preserve\">\n    <value>T</value>\n  </data>\n  <data name=\"tbInfo.Dock\" type=\"System.Windows.Forms.DockStyle, System.Windows.Forms\">\n    <value>Fill</value>\n  </data>\n  <data name=\"logTabs.Dock\" type=\"System.Windows.Forms.DockStyle, System.Windows.Forms\">\n    <value>Fill</value>\n  </data>\n  <data name=\"&gt;&gt;btn_RuleNew.Name\" xml:space=\"preserve\">\n    <value>btn_RuleNew</value>\n  </data>\n  <data name=\"&gt;&gt;MT_UI.Parent\" xml:space=\"preserve\">\n    <value>mainTabs</value>\n  </data>\n  <data name=\"lb_hk_extra.Text\" xml:space=\"preserve\">\n    <value>LB_HK_EXTRA</value>\n  </data>\n  <data name=\"cb_hk_key.Items51\" xml:space=\"preserve\">\n    <value>F5</value>\n  </data>\n  <data name=\"lb_AppName.Text\" xml:space=\"preserve\">\n    <value>VirtualSpace</value>\n  </data>\n  <data name=\"MT_About.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>5</value>\n  </data>\n  <data name=\"btn_m2.TextAlign\" type=\"System.Drawing.ContentAlignment, System.Drawing\">\n    <value>BottomCenter</value>\n  </data>\n  <data name=\"clearToolStripMenuItem.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>106, 22</value>\n  </data>\n  <data name=\"chb_RunOnStartup.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"logTabError.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1145, 663</value>\n  </data>\n  <data name=\"lb_note_configRoot.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>677, 53</value>\n  </data>\n  <data name=\"chb_HideOnStart.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>498, 20</value>\n  </data>\n  <data name=\"chb_HideMainViewIfItsShown.Text\" xml:space=\"preserve\">\n    <value>When use hotkey rise the MainView, Close it if the MainView already shown.</value>\n  </data>\n  <data name=\"&gt;&gt;btn_mouse_save.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_nav_circle_h.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>132, 21</value>\n  </data>\n  <data name=\"btn_PluginSettings.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"cb_hk_key.Items4\" xml:space=\"preserve\">\n    <value>D4</value>\n  </data>\n  <data name=\"&gt;&gt;gb_general.Parent\" xml:space=\"preserve\">\n    <value>tabPage_Genernal_Main</value>\n  </data>\n  <data name=\"panel_General.Dock\" type=\"System.Windows.Forms.DockStyle, System.Windows.Forms\">\n    <value>Fill</value>\n  </data>\n  <data name=\"lv_Plugins.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1104, 421</value>\n  </data>\n  <data name=\"&gt;&gt;btn_RuleEdit.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"&gt;&gt;tsb_plugins.Name\" xml:space=\"preserve\">\n    <value>tsb_plugins</value>\n  </data>\n  <data name=\"tsmiMainMenuRestart.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>202, 22</value>\n  </data>\n  <data name=\"lb_ui_vd_view.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"runAsAdministratorToolStripMenuItem.Text\" xml:space=\"preserve\">\n    <value>Run As Administrator</value>\n  </data>\n  <data name=\"&gt;&gt;chb_RunOnStartup.Name\" xml:space=\"preserve\">\n    <value>chb_RunOnStartup</value>\n  </data>\n  <data name=\"&gt;&gt;lbVersion.Name\" xml:space=\"preserve\">\n    <value>lbVersion</value>\n  </data>\n  <data name=\"fileToolStripMenuItem.Text\" xml:space=\"preserve\">\n    <value>File</value>\n  </data>\n  <data name=\"lvc_PluginAuthor.Width\" type=\"System.Int32, mscorlib\">\n    <value>300</value>\n  </data>\n  <data name=\"MT_Plugins.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>4</value>\n  </data>\n  <data name=\"&gt;&gt;rb_vdi_on_tray_style_1.Parent\" xml:space=\"preserve\">\n    <value>gb_Cluster</value>\n  </data>\n  <data name=\"btn_hk_RegAndSave.Text\" xml:space=\"preserve\">\n    <value>Register &amp;&amp; Save</value>\n  </data>\n  <data name=\"chb_RunOnStartup.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>230, 21</value>\n  </data>\n  <data name=\"panel_mask.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>8, 26</value>\n  </data>\n  <data name=\"chb_HideOnStart.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>22, 99</value>\n  </data>\n  <data name=\"lb_mouse_action.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"&gt;&gt;logTabEvent.ZOrder\" xml:space=\"preserve\">\n    <value>3</value>\n  </data>\n  <data name=\"&gt;&gt;toolStripSeparator1.Name\" xml:space=\"preserve\">\n    <value>toolStripSeparator1</value>\n  </data>\n  <data name=\"tlp_DesktopArrangement.LayoutSettings\" type=\"System.Windows.Forms.TableLayoutSettings, System.Windows.Forms\">\n    <value>&lt;?xml version=\"1.0\" encoding=\"utf-16\"?&gt;&lt;TableLayoutSettings&gt;&lt;Controls&gt;&lt;Control Name=\"btn_m7\" Row=\"1\" RowSpan=\"1\" Column=\"3\" ColumnSpan=\"1\" /&gt;&lt;Control Name=\"btn_m6\" Row=\"1\" RowSpan=\"1\" Column=\"2\" ColumnSpan=\"1\" /&gt;&lt;Control Name=\"btn_m5\" Row=\"1\" RowSpan=\"1\" Column=\"1\" ColumnSpan=\"1\" /&gt;&lt;Control Name=\"btn_m4\" Row=\"1\" RowSpan=\"1\" Column=\"0\" ColumnSpan=\"1\" /&gt;&lt;Control Name=\"btn_m3\" Row=\"0\" RowSpan=\"1\" Column=\"3\" ColumnSpan=\"1\" /&gt;&lt;Control Name=\"btn_m2\" Row=\"0\" RowSpan=\"1\" Column=\"2\" ColumnSpan=\"1\" /&gt;&lt;Control Name=\"btn_m1\" Row=\"0\" RowSpan=\"1\" Column=\"1\" ColumnSpan=\"1\" /&gt;&lt;Control Name=\"btn_m0\" Row=\"0\" RowSpan=\"1\" Column=\"0\" ColumnSpan=\"1\" /&gt;&lt;/Controls&gt;&lt;Columns Styles=\"Percent,25,Percent,25,Percent,25,Percent,25\" /&gt;&lt;Rows Styles=\"Percent,50,Percent,50\" /&gt;&lt;/TableLayoutSettings&gt;</value>\n  </data>\n  <data name=\"&gt;&gt;tabPage_Genernal_Main.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;chb_show_vd_name.Parent\" xml:space=\"preserve\">\n    <value>lb_ui_vd_view</value>\n  </data>\n  <data name=\"btn_RuleRemove.Text\" xml:space=\"preserve\">\n    <value>    Remove</value>\n  </data>\n  <data name=\"&gt;&gt;llb_goto_general.Name\" xml:space=\"preserve\">\n    <value>llb_goto_general</value>\n  </data>\n  <data name=\"cb_RuleProfiles.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>257, 25</value>\n  </data>\n  <data name=\"btn_m2.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"ts_PageNav.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>83, 718</value>\n  </data>\n  <data name=\"MT_About.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1169, 716</value>\n  </data>\n  <data name=\"mainMenu.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1291, 25</value>\n  </data>\n  <data name=\"cb_hk_key.Items39\" xml:space=\"preserve\">\n    <value>NumPad3</value>\n  </data>\n  <data name=\"&gt;&gt;lb_profiles_note.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;panel_General.Parent\" xml:space=\"preserve\">\n    <value>MT_General</value>\n  </data>\n  <data name=\"cb_hk_ctrl.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>47, 21</value>\n  </data>\n  <data name=\"gb_storage.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>6</value>\n  </data>\n  <data name=\"panel_General.AutoScroll\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"lvc_PluginVersion.Width\" type=\"System.Int32, mscorlib\">\n    <value>220</value>\n  </data>\n  <data name=\"btn_m2.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAL\n        DAAACwwBP0AiyAAADN9JREFUeF7tnIGx27YSRd1CWkgLvwW34BbcQlpIC27BLaSFtOAW0oKDy5j6EHQW\n        vEuAlN6Id+bM2CuRALGLxQKU/ennz58XbwwaL94HNF68D2i8eB/QePE+oPHifUDjxfuAxov3AY0X7wMa\n        L94HNF68D2h0aPS/wveCPhjlR+Fr4Qjpvn8WqF31/4/Cb4UzpHbU3l+Fti+y6bPfC6HIL1nQ6NBolvNr\n        PhdmSY7/p0DtEN8KRwWC7qv7U7uExhb7Qn7JgkaHRn8X6k7PQDNghvYGpzKRMttM6X66L7XXQ8H70Bfy\n        SxY0OjTKRLTLl8KoonTvImfNygRK55ks1KJr75YE8ksWNDo00iCNDnaNMsqotITQvYX6WjtWS0Q0MxXc\n        MxRlSWWoenb3+nI3LuSXLGh0mCSl+foBxUOk71SU+qPMooCIBn40C8ipdN8ouNReFDC61yLySxY0OkyQ\n        or5+sJUZqV+idKvquie13V4jRvtEzlSw9aRJ0F5zdx35JQsaHQYVzTal5hmKBs8pLPdeFykKdOeeUW21\n        7JDIL1nQ6DAoerAZ6/6qKACcreXswKRlTjxU9aAoIy39Ib9kQaPDgKKHmrHu16I2butnR7R0jGSAqDh2\n        pExJ1y6ThfySBY0OOxWl/pEBjkQnbFsVfbRzGDmUitK4K7pWoF+yoNFhpygdbhVDexVV3lFBF1Xeo/07\n        KgB+J79kQaPDDinFU3odmV1biraCdA4QbbuctbqnqAZwlryolhGfyS9Z0OiwQzQTtrZlo5KTaSlwGd3+\n        SVHN49QjURYTHyoARqryGYpmYYSCZnTmr1IQUuZzlhaql1a+kl+yoNEhKZr9R639rTSLegMZoT7P2plE\n        dUBve7n1EuvDBIBmQN3xlSMq/1Z73wSuaObOyFK9tbx9F6AlI6pHaj7MEhCl37oIO0KR85UN2uCTk3vB\n        MmM5yC5DW3yYANhzJj+qqHjSzOoFXu+6GdpTi0TXfIhtYFQBtzNwtqLK31nTo/V6VsGqMaFJ0bKOUdQf\n        9EsWNDqYitLqrAo7ErXpzuIoaEfeB5Dk4DZQ1+WpDlQK5uVZyC9Z0OhgKNr+yHakooJLM8nR6PWzRWP4\n        IV4GRTPp6PX/qABQNjtbypTUF40t+iULGh0MRW/BZqfSVtG289lLwFpgaka7NZC+1/ZD1y+FLPklCxod\n        DGnA646vuA8/oqhtp5CLCshl1u2U2m3vtzUO0RJ6C0TySxY0OmwomoViZCBd0cwRKrLqAqtVdN1t1u0U\n        bS91z14xTIGoa279J79kQaPDhqK1S/QcMEvR7BGyt7Nv6yBoNGtFdYVo7907ur77LvklCxodNkQpT2jw\n        z1K0lmdxa4ctRTWRy0MRSn7JgkaHDUUZ4Oyt1GgQKA2PpP5WUX2xBe5AyC9Z0OhgiNLY0QdAJKXfXnon\n        lKmUio9QdNxMdPtBfsmCRgdDcvZajetBzij+etJM1hoaHa2up3Bn9bPXF322GYDklyxodLj0fJFfsqDR\n        4dLzRX7JgkaHS88X+SULGh0uPV/klyxodLj0fJFfsqDR4dLzRX7JgkaHS88X+SULGh0GVZ/Q6XTs6AMi\n        7avX9rIc3T8dm6t/dHCmcwJ9hiK/ZEGjw4DoJEwPf5QyJ28RR/SvPijbAk8EyS9Z0OiwU3ro+sFqjppl\n        7iBvMfOdwN6gvHuXQn7JgkaHHdIAUppbcX6ssUfUVpaZGWA0I32IH4SQtl7IHBEAvYzjMrMG6PVHs7v+\n        rYTWfqV++u7yPfJLFjQ6JOW8Cz8iAOh18JH1xpai18EP6/svRQGzZAHySxY0OiTkvpM/IgCo+sd36ydI\n        z9f2RYRV/i+Fz0B+yYJGB1NKVVEaazkiAGjZua2hJ4v6orHZKi5pDJegIb9kQaODKarAo1rgiACg9qN0\n        e6TkZJoIbjbSUrAuH7edAPklCxodDNG6r/VXg9HaxREBQO3MKugyipbBoWAkv2RBo8OGogdeB58+mx0A\n        UQE1cz/vitZxMRSM5JcsaHToKFr362Kn/UzMDgAKQvVLUlvqT9tPpdm6n7MULXt1MKrddpeg/smOgUJ+\n        yYJGh46idb9W+7mYHQAauLYNLUHuyeDMQKA212BUoNKEadEY3mUv8ksWNDoEokhf1/1a7XfE7ACIZl0G\n        zcgZSwY5WOOSPRXUNbfDIvJLFjQ6gGjGCUpf9L3ZAeDO9C10n1HRfZ1ZT9wmFPklCxodGkUFV5RG6buz\n        A4DaEOvMq6W2exljdDmge9aoT20b0YQSL3USqGjUA9QdFO26X6v9rpgdAHTs2uuTFA26ZuvIUkD3XFGG\n        ie4dTSzxMv9HkLvu12q/L2YHgNbKdRmQA1VsOYoywUgWoPut3Nb0QFFQ/kF+yYJGh1+KOre1v6VrZgfA\n        Xqkf1L+t7NFTtN7fvd8PpIlE134nv2RBo0ORIrfu0IozU+i6VwkAifqnrLZXtEQK9ySQCtof5JcsaHQo\n        imb/DDTbtrLIkSKHjQRAtKy4QY/Xtz7ZAxodirJ72CwjKVfSmq8gdTJSq9kBEP0ews0AFAD/kF+yoNGh\n        SGvT3r2sw0gAtMfAmb18tOZqV7FXdCwt3OCkJeBv8ksWNDr8ktJ0lN5G0GCPLAG0BXRnW+Ss0d8R0GRx\n        AvNli8AR1Q+yMrMIpJQrB2xtuSSabWK0JlHFT/fd2p5GtdYX8ksWNDoMqn6QlZkBEG3l5Nze+UTkpJH0\n        vyraNfUCM3qOpR4hv2RBo8Og6odZmRkAEi0DQgPerr1qu/d9J3M4iopB6lM088WSNcgvWdDoMKj6YVZm\n        B4BStgaW2sqwlaKzipYYl1stQn7JgkaHQZFjZgeANBIEuu6IPmkJirLNFneFKPklCxodBtWutRrs3to8\n        It03Wtsj9P1ZaT9SL8W3KGs8BCP5JQsaHQZVzwI5f3aaJalNDXoUDNrO6vOjAjFS1CeNiz4Lx4b8kgWN\n        DpeeL/JLFjQ6XHq+yC9Z0Ohw6fkiv2RBo8Ol54v8kgWNDpeeL/JLFjQ6XHq+yC9Z0Ohw6fkiv2RBo8Me\n        lat+L/xYmv306a/C2Xtu7am1t45OB/WZOEs6qVR7dDyscxJ9Fo4R+SULGh32qFz199Lk/zlrsOV4+pVP\n        jyP7JsdnjoN1UPQg8ksWNDpkVa74c2nuHkX+0YrewDnISbOlYKS2tnh4lU1+yYJGh4zKt78uTT0y8js7\n        RyPOX7l7ATOovc5fufuZHPklCxodXJVvfl6aYY4MgN5gy6n1y57e7wHEjLeCao9qD81s9XWVZnkvcG8/\n        bSO/ZEGjg6PyrT+WJmKODIBoze85M3pRNGMpIKeqj1GRpxqk/b649YX8kgWNDj2VT1Xtf19u3+eoAFCR\n        VW7/gFPYRYEzumOh2b/1Q9WoL4vIL1nQ6EAq1t8KVOxFHBUA0exxnBil3zpN71F7P+fZo74syxf5JQsa\n        HWqVv2Udv3JmALj/ziD6By/uz8ojtbPZyUZRIL9OAJQ/yfnr4U6EagH6zpkB4BZy0aCPBoDaX+/1sKUL\n        FP1QZBH5JQsaHVaVP31ZbsPo4Efrsb53ZgBIdVXvzLZV0T90WZ7jRClAqG64ZTLySxY0Oqwqf1LBJ0vL\n        3aCXv58dAHuk1Fq69cBt1p2oaEdyy2TklyxodKhV/lZnAdUC9R57UbF9hACIZj8exR4kFZvRmYSKwpvI\n        L1nQ6JBVueLVAyBa+zX7HwJ6kjSbNQbUbsvDWQT5JQsaHbIqV7xyAESVv8jUDxlFazyB40R+yYJGh6zK\n        Fa8aAL1jV3fruEcKAGozQjuHu0KU/JIFjQ5ZlSteLQCU1qO1Vjyk3AMULTs9Xq8IdFSueKUA0ExS26UL\n        yJEz35H6F+0CxH9b6zKCo6DRIatyxasEQH0gQxy15u9RVJssv6Mgv2RBo0NW5YpXCIAt54+e9x+h8DyA\n        /JIFjQ5ZlSueHQC9Sl/9OPukz1X0u4aX+I8ibZUrnhkAPee75/IjUnDVW767A50NRaeT38gvWdDokFW5\n        4lkB0HP+GZW+pCBr23aDTsHTXiv+JL9kQaNDVuWKZwRAb80/83hXz9m27xab0VbxWgI2FM0ccfY2L3rH\n        4BwxU/As15JfsqDRIatyxdkBEB3yqM2j1/xWUSbaqj+6L6fIL1nQ6JBVueLMANja7mXRgI8GTeRMjYHq\n        lFr6O9UN4vZyivySBY0OWZUrKACWA40D1Dvf38vosqEAipyaQcG9iPySBY0OWZUr2n8WJo5ai48IgBnZ\n        SkHQe//QQzP/5nyJ/JIFjQ5ZlSvo3wi0qW+WegXgXmYGq57bfRUscAkiv2RBo8Melau+LU3+R+YwZI90\n        gqZZq86Ooll7xI9CFAhRtpLTu1tF8ksWNF68D2i8eB/QePE+oPHifUDjxfuAxov3AY0X7wMaL94HNF68\n        D2i8eBd+fvoXWkqEydvScvcAAAAASUVORK5CYII=\n</value>\n  </data>\n  <data name=\"&gt;&gt;lv_Rules.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ListView, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m1.Name\" xml:space=\"preserve\">\n    <value>btn_m1</value>\n  </data>\n  <data name=\"&gt;&gt;panel_PageNav.Name\" xml:space=\"preserve\">\n    <value>panel_PageNav</value>\n  </data>\n  <data name=\"tbDebug.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>3</value>\n  </data>\n  <data name=\"lb_hk_func.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"&gt;&gt;tabPage_Genernal_Keyboard.Parent\" xml:space=\"preserve\">\n    <value>tab_General</value>\n  </data>\n  <data name=\"&gt;&gt;panel_General.Name\" xml:space=\"preserve\">\n    <value>panel_General</value>\n  </data>\n  <data name=\"lb_profiles_note.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>4</value>\n  </data>\n  <data name=\"&gt;&gt;btn_profile_dup.Name\" xml:space=\"preserve\">\n    <value>btn_profile_dup</value>\n  </data>\n  <data name=\"MT_General.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"btn_RuleNew.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAu\n        IgAALiIBquLdkgAAAbVJREFUSEutlt0qBVEYhic2FyE5kJyLXISfAyIugRDiApRrUIiIe1CUwpH8lJ92\n        ckYccEJ+QlLb8+5ZZn9jz6wYvqen9lqr+d7ZzayZCYJC4LMSe3AO9/AGH/EW93EeezGHSceHJk6GjuEF\n        /oRLHMekPgkThaAedzEL+rcNGO/5baIJn/EvvGALlvqaQQ2+4X/wjrVYFpLHVNpgzdABdj2BM4yFDKKX\n        GbA1C3Y9hREsBlTgQ3HKwxTYmga7noJu90qFdLkJLxlDRI9ClqKhhwGwNQx23cOKQo6ioUMXWWdu2QJb\n        22DXRTvYPo4ThdxFQ8cxZKk82D6OO4WU7Y0NyFKbYPs4XhVyHw0dJ5ClUv7JvUKOo6FDG013j0XXwNYO\n        2HXRCbaP41Qhy9HQwyDY+sXdtaqQ7mjoQXePLZ25XffQqxDteO1MLxlDnjCnEDlUnPKQ8dk1isWAL/XU\n        TEUbbd2QcpEt5xj2jn6Ez3+9B/6DD6zDshDZjHqz/QVt7lYs9Y0NQvWO1pdIFg6xEeM9yyZKTuAV/oRr\n        nMSkPgkTcauwDxfwAPW99fXdpbNexH6sxqTjMQg+Aa1zHP0aaDh2AAAAAElFTkSuQmCC\n</value>\n  </data>\n  <data name=\"&gt;&gt;panel_UI.Parent\" xml:space=\"preserve\">\n    <value>MT_UI</value>\n  </data>\n  <data name=\"&gt;&gt;tabPage_Genernal_Mouse.Name\" xml:space=\"preserve\">\n    <value>tabPage_Genernal_Mouse</value>\n  </data>\n  <data name=\"&gt;&gt;MT_General.Name\" xml:space=\"preserve\">\n    <value>MT_General</value>\n  </data>\n  <data name=\"llb_goto_general.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>290, 27</value>\n  </data>\n  <data name=\"tbError.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1145, 663</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m7.Parent\" xml:space=\"preserve\">\n    <value>tlp_DesktopArrangement</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m5.ZOrder\" xml:space=\"preserve\">\n    <value>2</value>\n  </data>\n  <data name=\"btn_m5.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>5</value>\n  </data>\n  <data name=\"&gt;&gt;gb_profiles.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"btn_m4.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>2, 242</value>\n  </data>\n  <data name=\"&gt;&gt;tbVerbose.Parent\" xml:space=\"preserve\">\n    <value>logTabVerbose</value>\n  </data>\n  <data name=\"btn_profile_del.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>101, 25</value>\n  </data>\n  <data name=\"&gt;&gt;tv_keyboard.Parent\" xml:space=\"preserve\">\n    <value>tabPage_Genernal_Keyboard</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m2.ZOrder\" xml:space=\"preserve\">\n    <value>5</value>\n  </data>\n  <data name=\"lb_RunOnStartup.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>2</value>\n  </data>\n  <data name=\"btn_m4.TextAlign\" type=\"System.Drawing.ContentAlignment, System.Drawing\">\n    <value>BottomCenter</value>\n  </data>\n  <data name=\"btn_RuleEdit.ImageAlign\" type=\"System.Drawing.ContentAlignment, System.Drawing\">\n    <value>MiddleLeft</value>\n  </data>\n  <data name=\"btn_RuleClone.Text\" xml:space=\"preserve\">\n    <value>    Clone</value>\n  </data>\n  <data name=\"&gt;&gt;panel_General.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Panel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;tp_hk_main.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;cb_mouse_func.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m5.Parent\" xml:space=\"preserve\">\n    <value>tlp_DesktopArrangement</value>\n  </data>\n  <data name=\"&gt;&gt;lv_Rules.Name\" xml:space=\"preserve\">\n    <value>lv_Rules</value>\n  </data>\n  <data name=\"&gt;&gt;tp_hk_extra.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_nav_circle_h.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>22, 26</value>\n  </data>\n  <data name=\"btn_RuleNew.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>6, 0, 0, 0</value>\n  </data>\n  <data name=\"&gt;&gt;lb_hk_extra.Parent\" xml:space=\"preserve\">\n    <value>tp_hk_extra</value>\n  </data>\n  <data name=\"tsb_general.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO\n        wQAADsEBuJFr7QAABnZJREFUeF7tms9vVFUUx+vCndU9f4I7XJhYJBDAGJTWIFhoBBIxGgligVAgcdEd\n        iQtX7gymKSpgZOFCBFExGCKg/CoZaBGYdub9mE7nV2feMJRYOd7vffcMt2/ezHQ6U50Z3kk+mfvj3Dvn\n        fN89L9P32hFYYIEFFlhggdVk5uRMjzGVDUciudxCMKdy96KTziG1XUfUdg5hzM93PhiJbHjCnFmntltc\n        u0z0tDmVeWDGc2QI7IRDUymH4snqwA/+0Ul3XSw+/SlA2xBj2BPEsZ+g2Md6/TtUm+eBFZ8uIDYV5uJZ\n        Op1+LhQKzXLyMcGEnaVIrDrwgz8SsKcc+u68LcEY4GTY39v3wvMAMSE2FebimjHtZK24G/TpSzE6ciZK\n        x3426GgFMA8/+KcyeXkKvvghIoEwU+rqIrEjZ+BrCJGEyIJjv5g0dDpKX/1kSNDGGHyxBnshJhVe/dYz\n        kOjU2a4+u3oSnZ8dTSxx8o6TyrhX/siPUTp8MkJfiuSqAT/4W+KKxURinBAnslABYskcISbEhhj1mHVU\n        euWtd7fZvXm3Ed6wM5IDmwWbFGiveU+wI5IbHBx8dP9BXgaAq4vkLo0l6eqdNP15O1UCxjEPP/hzYn4C\n        uOXhzstaV30uMwtzCXeej/+04xBiQmyIUY9bB7m9ucvsVumW2hv99oONH5n0Vr8lQXvzXos27XFZ94FJ\n        W/fbdDeapXyh8QLgE/A82kgcbV0MKYKABcjkHBkTYkOMHK8ve62CSrfUnt8Vmu0ViQ+dfShBe8Ouxxti\n        820HbLpnPBbgm7MmDYtj/bVIBBwXfcB9HfjBnxNkAbjvPeqAj7vu8/n3kTklAAEQE2KrKsCe0KxKt9Rw\n        7OsVAFcZ6IkzTSGAyFGlW2qonWol4BWgWAKjSQknq5fEfEtAjov6xhHHGHBr3j3+lUqgIQLIG4VIGFcd\n        6MmDSgIgSVCLAEOnohJdAE6umLBIvlSQRRTAd5GikgB8wzsujib6LISOtwRwjMsdb32sXFmwcC0nAAfO\n        SaKNsbYQgJOtVAJeAfgoo11SAqqvlwGPNWUJzEcATgBXUb+SctzvJqjQRcF4UwpQyz2Ab4Lc9zvu+pFn\n        P/6pzMK1rACcIPfbQgBOdj4lwAlyIjwOSsrA57dAy98DygnAdV9M2PNbgP1a/h7AAnCfS8B75L2lwfMs\n        XCBAMwiAYw442YaWgGhXeh7QFAI07I8hBdf8fJ8H/OcC4ImQ3yOxYXE8Afd15jwSE1eRBeCkvUcd+JXD\n        ov05XIsAuXx+zkNRXFmAGgfeh6T6Q9FkJi+vXNML0DcQo759ttsWn907bXrn40mKZxyapQI5M/cpL0g5\n        DqWdfFXgB/+Hfxdk+8R5U5IWYhYeFuSn3zqMZwv3JWinPGP/iFgQE2JDjHrMyEHPqSYBevtNCbdff9+g\n        LfssunknQ3Y8S3cmpikcFTcnU9ykTFGvVYAf/MfF1Robz9DQSXHHF4yFMzQhxtjHuwaf+C6gj92NuGOI\n        BTEhNsSox8ztIvMRoG9fTC5ctuoaLX/lBm380KAVa0PUteIqLV89QqvXjtCa1wT4XCDYY+Wr1yVyv3oQ\n        sWAPxIYYEStiRuzIAbkgp7oFWLbyGr286jq90HWdlr50jZZ2LRCxFnu8uHxE0qj9EBtirFsABguB3m4V\n        vPEXqUUA703Q7Tc5PjHrOdUkQFsSCFBJgD2hWd9FbUWFN0N4N+i/qD7wfqF3t0U9O8w5rN9pSbzj8PW+\n        k2gY71Z4N9h3wOxe32+EZSk0CPm2SYC3tlsGBh9tO2jT1v2W5O0BF+5jDj7wxZpyb3kXStW3w2ze9+r1\n        0rU90fnJ4cSSS+G08/vNFF24mabfbiRp+JQhQRtjmIMPfLHGb696UOn9fzZipLM3xtN0K5qhkfEUfXvO\n        kKCNMczBR7m3l42OJjovXknl/hhL0ZW/0nRRe3aANsYwBx/4qmXtY+dFUiLBogAXbokSEH/qArRZAPjA\n        Vy1rH9MFuHw7LTlxzpJcFsmj/8QIAPghKsPj8HkiBAB8EvQxwZMjQBnaUwDYryNG9uKouNNXAD7KvTWN\n        iJ5KJBKdXkYj4ofQaMrx1r4X+MDXbw/srb6meS0ejz9j2tNW6X91O/IfLOW/tZYBc/CBr3c99sTe6mua\n        15LJ5LP8wsILP9quht9agL3V1zSvVRKgXlpCgPIlUB8tUwKBBRZYYIEF1irW0fEvIzODxTbuOToAAAAA\n        SUVORK5CYII=\n</value>\n  </data>\n  <data name=\"btn_RuleEdit.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>3</value>\n  </data>\n  <data name=\"btn_RuleClone.ImageAlign\" type=\"System.Drawing.ContentAlignment, System.Drawing\">\n    <value>MiddleLeft</value>\n  </data>\n  <data name=\"lb_MouseOnTaskbarSwitchDesktop2.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"lb_hk_func.Font\" type=\"System.Drawing.Font, System.Drawing\">\n    <value>Microsoft YaHei UI, 9pt, style=Bold</value>\n  </data>\n  <data name=\"tsb_logs.TextImageRelation\" type=\"System.Windows.Forms.TextImageRelation, System.Windows.Forms\">\n    <value>ImageAboveText</value>\n  </data>\n  <data name=\"btn_PluginSettings.ImageAlign\" type=\"System.Drawing.ContentAlignment, System.Drawing\">\n    <value>MiddleLeft</value>\n  </data>\n  <data name=\"btn_RuleClone.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>5</value>\n  </data>\n  <data name=\"cb_hk_ctrl.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"&gt;&gt;MT_General.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;lvc_PluginVersion.Name\" xml:space=\"preserve\">\n    <value>lvc_PluginVersion</value>\n  </data>\n  <data name=\"&gt;&gt;panel_PageNav.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Panel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"lb_nav_circle_h_type.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 0, 2, 0</value>\n  </data>\n  <data name=\"chb_HideMainViewIfItsShown.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>22, 27</value>\n  </data>\n  <data name=\"btn_m2.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"&gt;&gt;panel_PageNav.ZOrder\" xml:space=\"preserve\">\n    <value>3</value>\n  </data>\n  <data name=\"gb_profiles.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>7</value>\n  </data>\n  <data name=\"lb_configRoot.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"&gt;&gt;tsmiMainMenuRestart.Name\" xml:space=\"preserve\">\n    <value>tsmiMainMenuRestart</value>\n  </data>\n  <data name=\"lvc_PluginName.Width\" type=\"System.Int32, mscorlib\">\n    <value>300</value>\n  </data>\n  <data name=\"llb_Company.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>63, 17</value>\n  </data>\n  <data name=\"chb_HideOnStart.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"&gt;&gt;rb_vdi_on_tray_style_1.Name\" xml:space=\"preserve\">\n    <value>rb_vdi_on_tray_style_1</value>\n  </data>\n  <data name=\"&gt;&gt;mainTabs.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TabControl, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"logTabs.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>0</value>\n  </data>\n  <data name=\"tsb_general.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>81, 105</value>\n  </data>\n  <data name=\"&gt;&gt;chb_show_vd_name.ZOrder\" xml:space=\"preserve\">\n    <value>3</value>\n  </data>\n  <data name=\"&gt;&gt;tbInfo.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;btn_profile_del.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"gb_storage.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>778, 120</value>\n  </data>\n  <data name=\"&gt;&gt;tb_hk_tip.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;MT_About.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"tbError.Dock\" type=\"System.Windows.Forms.DockStyle, System.Windows.Forms\">\n    <value>Fill</value>\n  </data>\n  <data name=\"gb_general.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>10, 10</value>\n  </data>\n  <data name=\"gb_CurrentProfile.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"mainMenu.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>4, 2, 0, 2</value>\n  </data>\n  <data name=\"&gt;&gt;btn_m2.Name\" xml:space=\"preserve\">\n    <value>btn_m2</value>\n  </data>\n  <data name=\"tsb_rules.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n        GkC7obKg/QAAAABJRU5ErkJggg==\n</value>\n  </data>\n  <data name=\"cb_RuleProfiles.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"lvc_Updated.TextAlign\" type=\"System.Windows.Forms.HorizontalAlignment, System.Windows.Forms\">\n    <value>Right</value>\n  </data>\n  <data name=\"gb_Rules.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1137, 542</value>\n  </data>\n  <data name=\"&gt;&gt;tbInfo.Name\" xml:space=\"preserve\">\n    <value>tbInfo</value>\n  </data>\n  <data name=\"lb_DesktopArrangementNote.Font\" type=\"System.Drawing.Font, System.Drawing\">\n    <value>Microsoft YaHei UI, 9pt, style=Bold</value>\n  </data>\n  <data name=\"cb_hk_key.Items31\" xml:space=\"preserve\">\n    <value>U</value>\n  </data>\n  <data name=\"closeThisWindowToolStripMenuItem.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>202, 22</value>\n  </data>\n  <data name=\"&gt;&gt;$this.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Form, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"chb_show_vd_index.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>1</value>\n  </data>\n  <data name=\"cb_hk_key.Items28\" xml:space=\"preserve\">\n    <value>R</value>\n  </data>\n  <data name=\"lb_profiles_note.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"&gt;&gt;tbVerbose.Name\" xml:space=\"preserve\">\n    <value>tbVerbose</value>\n  </data>\n  <data name=\"panel_Pages.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>2</value>\n  </data>\n  <data name=\"gb_storage.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;tb_hk_tip.Name\" xml:space=\"preserve\">\n    <value>tb_hk_tip</value>\n  </data>\n  <data name=\"&gt;&gt;btn_RuleNew.Parent\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <data name=\"lb_mouse_action.Font\" type=\"System.Drawing.Font, System.Drawing\">\n    <value>Microsoft YaHei UI, 9pt, style=Bold</value>\n  </data>\n  <data name=\"cb_hk_key.Items14\" xml:space=\"preserve\">\n    <value>D</value>\n  </data>\n  <data name=\"&gt;&gt;runAsAdministratorToolStripMenuItem.Name\" xml:space=\"preserve\">\n    <value>runAsAdministratorToolStripMenuItem</value>\n  </data>\n  <data name=\"&gt;&gt;closeThisWindowToolStripMenuItem.Name\" xml:space=\"preserve\">\n    <value>closeThisWindowToolStripMenuItem</value>\n  </data>\n  <data name=\"cb_hk_key.Items37\" xml:space=\"preserve\">\n    <value>NumPad1</value>\n  </data>\n  <data name=\"$this.AutoScaleDimensions\" type=\"System.Drawing.SizeF, System.Drawing\">\n    <value>7, 17</value>\n  </data>\n  <data name=\"&gt;&gt;logTabWarning.ZOrder\" xml:space=\"preserve\">\n    <value>4</value>\n  </data>\n  <data name=\"btn_RuleNew.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"&gt;&gt;tbInfo.Parent\" xml:space=\"preserve\">\n    <value>logTabInfo</value>\n  </data>\n  <data name=\"btn_m7.Dock\" type=\"System.Windows.Forms.DockStyle, System.Windows.Forms\">\n    <value>Fill</value>\n  </data>\n  <data name=\"&gt;&gt;lv_Rules.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;lb_configRoot.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"lvc_Updated.Width\" type=\"System.Int32, mscorlib\">\n    <value>220</value>\n  </data>\n  <data name=\"btn_RuleClone.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>921, 455</value>\n  </data>\n  <data name=\"llb_Company.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"cb_nav_circle_v.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"gb_DesktopArrangement.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1136, 585</value>\n  </data>\n  <data name=\"&gt;&gt;lvc_PluginVersion.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ColumnHeader, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"tsb_logs.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>81, 105</value>\n  </data>\n  <data name=\"cb_hk_win.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>13, 47</value>\n  </data>\n  <data name=\"&gt;&gt;cb_nav_circle_v.ZOrder\" xml:space=\"preserve\">\n    <value>2</value>\n  </data>\n  <data name=\"tbWarning.ScrollBars\" type=\"System.Windows.Forms.ScrollBars, System.Windows.Forms\">\n    <value>Vertical</value>\n  </data>\n  <data name=\"gb_DesktopArrangement.Text\" xml:space=\"preserve\">\n    <value>Virtual Desktop Arrangement</value>\n  </data>\n  <data name=\"cb_hk_key.Items\" xml:space=\"preserve\">\n    <value>None</value>\n  </data>\n  <data name=\"&gt;&gt;cb_hk_ctrl.ZOrder\" xml:space=\"preserve\">\n    <value>7</value>\n  </data>\n  <data name=\"logTabEvent.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1145, 663</value>\n  </data>\n  <data name=\"&gt;&gt;logTabInfo.Parent\" xml:space=\"preserve\">\n    <value>logTabs</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_profiles.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;lb_MouseOnTaskbarSwitchDesktop2.Name\" xml:space=\"preserve\">\n    <value>lb_MouseOnTaskbarSwitchDesktop2</value>\n  </data>\n  <data name=\"cb_nav_circle_h.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;btn_profile_dup.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;tbEvent.Parent\" xml:space=\"preserve\">\n    <value>logTabEvent</value>\n  </data>\n  <data name=\"tp_hk_extra.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>4, 26</value>\n  </data>\n  <data name=\"btn_m4.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n</value>\n  </data>\n  <data name=\"&gt;&gt;cb_nav_circle_h_type.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"tv_mouse.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>420, 500</value>\n  </data>\n  <data name=\"MT_Rules.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1169, 716</value>\n  </data>\n  <data name=\"btn_RuleClone.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"tsb_rules.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>81, 105</value>\n  </data>\n  <data name=\"tbEvent.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>3</value>\n  </data>\n  <data name=\"btn_m0.Dock\" type=\"System.Windows.Forms.DockStyle, System.Windows.Forms\">\n    <value>Fill</value>\n  </data>\n  <data name=\"&gt;&gt;mainTabs.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"cb_hk_key.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>211, 46</value>\n  </data>\n  <data name=\"btn_m2.Text\" xml:space=\"preserve\">\n    <value>BottomLeft to TopRight, Horizontal</value>\n  </data>\n  <data name=\"&gt;&gt;lvc_Name.Name\" xml:space=\"preserve\">\n    <value>lvc_Name</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_1.Text\" xml:space=\"preserve\">\n    <value>High Contrast 1</value>\n  </data>\n  <data name=\"&gt;&gt;mainMenu.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.MenuStrip, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_RuleProfiles.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>11, 23</value>\n  </data>\n  <data name=\"&gt;&gt;tsb_about.Name\" xml:space=\"preserve\">\n    <value>tsb_about</value>\n  </data>\n  <data name=\"&gt;&gt;lb_MouseOnTaskbarSwitchDesktop1.ZOrder\" xml:space=\"preserve\">\n    <value>2</value>\n  </data>\n  <data name=\"&gt;&gt;llb_Company.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"&gt;&gt;lb_nav_circle_h_type.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"gb_DesktopArrangement.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;MT_UI.Name\" xml:space=\"preserve\">\n    <value>MT_UI</value>\n  </data>\n  <data name=\"&gt;&gt;tbEvent.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;lb_note_configRoot.ZOrder\" xml:space=\"preserve\">\n    <value>3</value>\n  </data>\n  <data name=\"btn_m3.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>3</value>\n  </data>\n  <data name=\"rb_vd_index_1.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>284, 58</value>\n  </data>\n  <data name=\"&gt;&gt;lb_mouse_action.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;MT_Plugins.Parent\" xml:space=\"preserve\">\n    <value>mainTabs</value>\n  </data>\n  <data name=\"lb_Version.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>52, 17</value>\n  </data>\n  <data name=\"&gt;&gt;btn_profile_rename.ZOrder\" xml:space=\"preserve\">\n    <value>2</value>\n  </data>\n  <data name=\"tlp_DesktopArrangement.ColumnCount\" type=\"System.Int32, mscorlib\">\n    <value>4</value>\n  </data>\n  <data name=\"&gt;&gt;lb_hk_extra.Name\" xml:space=\"preserve\">\n    <value>lb_hk_extra</value>\n  </data>\n  <data name=\"&gt;&gt;ts_PageNav.Parent\" xml:space=\"preserve\">\n    <value>panel_PageNav</value>\n  </data>\n  <data name=\"&gt;&gt;btn_RuleClone.ZOrder\" xml:space=\"preserve\">\n    <value>2</value>\n  </data>\n  <data name=\"&gt;&gt;btn_profile_del.Parent\" xml:space=\"preserve\">\n    <value>gb_profiles</value>\n  </data>\n  <data name=\"&gt;&gt;cb_hk_shift.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"tbWarning.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>0, 0</value>\n  </data>\n  <data name=\"&gt;&gt;chb_HideMainViewIfItsShown.ZOrder\" xml:space=\"preserve\">\n    <value>6</value>\n  </data>\n  <data name=\"&gt;&gt;lb_hk_func.ZOrder\" xml:space=\"preserve\">\n    <value>3</value>\n  </data>\n  <data name=\"cb_hk_key.Items42\" xml:space=\"preserve\">\n    <value>NumPad6</value>\n  </data>\n  <data name=\"&gt;&gt;gb_nav.Parent\" xml:space=\"preserve\">\n    <value>tabPage_Genernal_Main</value>\n  </data>\n  <data name=\"tsb_logs.Text\" xml:space=\"preserve\">\n    <value>Logs</value>\n  </data>\n  <data name=\"tab_General.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>1153, 693</value>\n  </data>\n  <data name=\"$this.StartPosition\" type=\"System.Windows.Forms.FormStartPosition, System.Windows.Forms\">\n    <value>CenterScreen</value>\n  </data>\n  <data name=\"mainStatusStrip.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>6</value>\n  </data>\n  <data name=\"&gt;&gt;logsToolStripMenuItem.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;lbox_Env.Name\" xml:space=\"preserve\">\n    <value>lbox_Env</value>\n  </data>\n  <data name=\"&gt;&gt;rb_vdi_on_tray_style_1.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"cb_hk_key.Items66\" xml:space=\"preserve\">\n    <value>PageUp</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Cluster.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;btn_RuleClone.Name\" xml:space=\"preserve\">\n    <value>btn_RuleClone</value>\n  </data>\n  <data name=\"rb_vd_index_1.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>74, 21</value>\n  </data>\n  <data name=\"chb_notify_vd_changed.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>22, 51</value>\n  </data>\n  <data name=\"lb_ui_vd_view.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>1</value>\n  </data>\n  <data name=\"&gt;&gt;tc_Mouse.Name\" xml:space=\"preserve\">\n    <value>tc_Mouse</value>\n  </data>\n  <data name=\"&gt;&gt;tbDebug.Name\" xml:space=\"preserve\">\n    <value>tbDebug</value>\n  </data>\n  <data name=\"&gt;&gt;tbError.Parent\" xml:space=\"preserve\">\n    <value>logTabError</value>\n  </data>\n  <data name=\"&gt;&gt;showLogsInGuiToolStripMenuItem.Name\" xml:space=\"preserve\">\n    <value>showLogsInGuiToolStripMenuItem</value>\n  </data>\n  <data name=\"btn_m2.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>2</value>\n  </data>\n  <data name=\"showLogsInGuiToolStripMenuItem.Text\" xml:space=\"preserve\">\n    <value>Show Full Logs In GUI</value>\n  </data>\n  <data name=\"cb_hk_key.Items48\" xml:space=\"preserve\">\n    <value>F2</value>\n  </data>\n  <data name=\"lb_MouseOnTaskbarSwitchDesktop2.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>413, 17</value>\n  </data>\n  <data name=\"&gt;&gt;lbox_Env.ZOrder\" xml:space=\"preserve\">\n    <value>2</value>\n  </data>\n  <data name=\"btn_hk_ClearAndSave.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>9</value>\n  </data>\n  <data name=\"&gt;&gt;tv_mouse.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"lb_profiles_note.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>739, 43</value>\n  </data>\n  <data name=\"btn_m7.Text\" xml:space=\"preserve\">\n    <value>BottomRight to TopLeft, Vertical</value>\n  </data>\n  <data name=\"chb_show_vd_name.Text\" xml:space=\"preserve\">\n    <value>Show Virtual Desktop Name</value>\n  </data>\n  <data name=\"cb_hk_key.Items6\" xml:space=\"preserve\">\n    <value>D6</value>\n  </data>\n  <data name=\"&gt;&gt;mainTabs.Name\" xml:space=\"preserve\">\n    <value>mainTabs</value>\n  </data>\n  <data name=\"&gt;&gt;btn_mouse_save.Name\" xml:space=\"preserve\">\n    <value>btn_mouse_save</value>\n  </data>\n  <data name=\"btn_profile_dup.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>1</value>\n  </data>\n  <data name=\"&gt;&gt;rb_vd_index_0.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"gb_Rules.Text\" xml:space=\"preserve\">\n    <value>Rules</value>\n  </data>\n  <data name=\"&gt;&gt;tbError.Name\" xml:space=\"preserve\">\n    <value>tbError</value>\n  </data>\n  <data name=\"btn_RuleRemove.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>4</value>\n  </data>\n  <data name=\"lb_DesktopArrangementNote.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>909, 42</value>\n  </data>\n  <data name=\"cb_hk_key.Items36\" xml:space=\"preserve\">\n    <value>Z</value>\n  </data>\n  <data name=\"ts_PageNav.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>0, 1, 1, 0</value>\n  </data>\n  <data name=\"&gt;&gt;closeThisWindowToolStripMenuItem.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"gb_Cluster.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>778, 140</value>\n  </data>\n  <data name=\"aboutToolStripMenuItem.Text\" xml:space=\"preserve\">\n    <value>About</value>\n  </data>\n  <data name=\"btn_PluginSettings.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>1020, 455</value>\n  </data>\n  <data name=\"&gt;&gt;cb_hk_alt.Name\" xml:space=\"preserve\">\n    <value>cb_hk_alt</value>\n  </data>\n  <data name=\"&gt;&gt;pb_AboutLogo.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.PictureBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_nav_circle_h_type.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>227, 25</value>\n  </data>\n  <data name=\"cb_hk_key.Items43\" xml:space=\"preserve\">\n    <value>NumPad7</value>\n  </data>\n  <data name=\"tp_hk_main.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"lb_AppName.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>17</value>\n  </data>\n  <data name=\"lv_Rules.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_2.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>9</value>\n  </data>\n  <data name=\"MT_Plugins.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"lvc_Created.Width\" type=\"System.Int32, mscorlib\">\n    <value>220</value>\n  </data>\n  <data name=\"&gt;&gt;cb_hk_alt.ZOrder\" xml:space=\"preserve\">\n    <value>6</value>\n  </data>\n  <data name=\"&gt;&gt;logTabVerbose.ZOrder\" xml:space=\"preserve\">\n    <value>2</value>\n  </data>\n  <data name=\"tsb_general.ImageTransparentColor\" type=\"System.Drawing.Color, System.Drawing\">\n    <value>Magenta</value>\n  </data>\n  <data name=\"&gt;&gt;tp_hk_extra.Parent\" xml:space=\"preserve\">\n    <value>tc_Keyboard</value>\n  </data>\n  <data name=\"&gt;&gt;llb_goto_general.Parent\" xml:space=\"preserve\">\n    <value>gb_CurrentProfile</value>\n  </data>\n  <data name=\"&gt;&gt;logTabEvent.Parent\" xml:space=\"preserve\">\n    <value>logTabs</value>\n  </data>\n  <data name=\"tbDebug.ScrollBars\" type=\"System.Windows.Forms.ScrollBars, System.Windows.Forms\">\n    <value>Vertical</value>\n  </data>\n  <data name=\"lb_configRoot.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 0, 2, 0</value>\n  </data>\n  <data name=\"llb_goto_general.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>224, 17</value>\n  </data>\n  <data name=\"&gt;&gt;llb_TaskScheduler.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.LinkLabel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;tp_mouse_action.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"tv_keyboard.Nodes1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n    <value>\n        AAEAAAD/////AQAAAAAAAAAMAgAAAEZTeXN0ZW0uV2luZG93cy5Gb3JtcywgQ3VsdHVyZT1uZXV0cmFs\n        LCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAdU3lzdGVtLldpbmRvd3MuRm9ybXMu\n        VHJlZU5vZGULAAAABFRleHQLVG9vbFRpcFRleHQETmFtZQlJc0NoZWNrZWQKSW1hZ2VJbmRleAhJbWFn\n        ZUtleRJTZWxlY3RlZEltYWdlSW5kZXgQU2VsZWN0ZWRJbWFnZUtleQpDaGlsZENvdW50CWNoaWxkcmVu\n        MAljaGlsZHJlbjEBAQEAAAEAAQAEBAEICAgdU3lzdGVtLldpbmRvd3MuRm9ybXMuVHJlZU5vZGUCAAAA\n        HVN5c3RlbS5XaW5kb3dzLkZvcm1zLlRyZWVOb2RlAgAAAAIAAAAGAwAAAAdEZXNrdG9wBgQAAAAABgUA\n        AAAPaGtfcm9vdF9kZXNrdG9wAP////8JBAAAAP////8JBAAAAAIAAAAJBwAAAAkIAAAABQcAAAAdU3lz\n        dGVtLldpbmRvd3MuRm9ybXMuVHJlZU5vZGUJAAAABFRleHQLVG9vbFRpcFRleHQETmFtZQlJc0NoZWNr\n        ZWQKSW1hZ2VJbmRleAhJbWFnZUtleRJTZWxlY3RlZEltYWdlSW5kZXgQU2VsZWN0ZWRJbWFnZUtleQpD\n        aGlsZENvdW50AQEBAAABAAEAAQgICAIAAAAGCQAAAAZTd2l0Y2gJBAAAAAYLAAAADWhrX3BhcmVudF9z\n        dmQA/////wkEAAAA/////wkEAAAAAAAAAAUIAAAAHVN5c3RlbS5XaW5kb3dzLkZvcm1zLlRyZWVOb2Rl\n        DQAAAARUZXh0C1Rvb2xUaXBUZXh0BE5hbWUJSXNDaGVja2VkCkltYWdlSW5kZXgISW1hZ2VLZXkSU2Vs\n        ZWN0ZWRJbWFnZUluZGV4EFNlbGVjdGVkSW1hZ2VLZXkKQ2hpbGRDb3VudAljaGlsZHJlbjAJY2hpbGRy\n        ZW4xCWNoaWxkcmVuMgljaGlsZHJlbjMBAQEAAAEAAQAEBAQEAQgICB1TeXN0ZW0uV2luZG93cy5Gb3Jt\n        cy5UcmVlTm9kZQIAAAAdU3lzdGVtLldpbmRvd3MuRm9ybXMuVHJlZU5vZGUCAAAAHVN5c3RlbS5XaW5k\n        b3dzLkZvcm1zLlRyZWVOb2RlAgAAAB1TeXN0ZW0uV2luZG93cy5Gb3Jtcy5UcmVlTm9kZQIAAAACAAAA\n        Bg0AAAAKTmF2aWdhdGlvbgkEAAAABg8AAAAQaGtfcGFyZW50X25hdl92ZAD/////CQQAAAD/////CQQA\n        AAAEAAAACREAAAAJEgAAAAkTAAAACRQAAAAFEQAAAB1TeXN0ZW0uV2luZG93cy5Gb3Jtcy5UcmVlTm9k\n        ZQkAAAAEVGV4dAtUb29sVGlwVGV4dAROYW1lCUlzQ2hlY2tlZApJbWFnZUluZGV4CEltYWdlS2V5ElNl\n        bGVjdGVkSW1hZ2VJbmRleBBTZWxlY3RlZEltYWdlS2V5CkNoaWxkQ291bnQBAQEAAAEAAQABCAgIAgAA\n        AAYVAAAABExlZnQJBAAAAAYXAAAAEGhrX25vZGVfbmF2X2xlZnQA/////wkEAAAA/////wkEAAAAAAAA\n        AAUSAAAAHVN5c3RlbS5XaW5kb3dzLkZvcm1zLlRyZWVOb2RlCQAAAARUZXh0C1Rvb2xUaXBUZXh0BE5h\n        bWUJSXNDaGVja2VkCkltYWdlSW5kZXgISW1hZ2VLZXkSU2VsZWN0ZWRJbWFnZUluZGV4EFNlbGVjdGVk\n        SW1hZ2VLZXkKQ2hpbGRDb3VudAEBAQAAAQABAAEICAgCAAAABhkAAAAFUmlnaHQJBAAAAAYbAAAAEWhr\n        X25vZGVfbmF2X3JpZ2h0AP////8JBAAAAP////8JBAAAAAAAAAAFEwAAAB1TeXN0ZW0uV2luZG93cy5G\n        b3Jtcy5UcmVlTm9kZQkAAAAEVGV4dAtUb29sVGlwVGV4dAROYW1lCUlzQ2hlY2tlZApJbWFnZUluZGV4\n        CEltYWdlS2V5ElNlbGVjdGVkSW1hZ2VJbmRleBBTZWxlY3RlZEltYWdlS2V5CkNoaWxkQ291bnQBAQEA\n        AAEAAQABCAgIAgAAAAYdAAAAAlVwCQQAAAAGHwAAAA5oa19ub2RlX25hdl91cAD/////CQQAAAD/////\n        CQQAAAAAAAAABRQAAAAdU3lzdGVtLldpbmRvd3MuRm9ybXMuVHJlZU5vZGUJAAAABFRleHQLVG9vbFRp\n        cFRleHQETmFtZQlJc0NoZWNrZWQKSW1hZ2VJbmRleAhJbWFnZUtleRJTZWxlY3RlZEltYWdlSW5kZXgQ\n        U2VsZWN0ZWRJbWFnZUtleQpDaGlsZENvdW50AQEBAAABAAEAAQgICAIAAAAGIQAAAAREb3duCQQAAAAG\n        IwAAABBoa19ub2RlX25hdl9kb3duAP////8JBAAAAP////8JBAAAAAAAAAAL\n</value>\n  </data>\n  <data name=\"btn_m4.Text\" xml:space=\"preserve\">\n    <value>TopLeft to BottomRight, Vertical</value>\n  </data>\n  <data name=\"btn_RuleNew.ImageAlign\" type=\"System.Drawing.ContentAlignment, System.Drawing\">\n    <value>MiddleLeft</value>\n  </data>\n  <data name=\"panel_UI.Dock\" type=\"System.Windows.Forms.DockStyle, System.Windows.Forms\">\n    <value>Fill</value>\n  </data>\n  <data name=\"lb_DesktopArrangementNote.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 0, 2, 0</value>\n  </data>\n  <data name=\"&gt;&gt;btn_chooseConfigRoot.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"pb_AboutLogo.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;btn_mouse_save.Parent\" xml:space=\"preserve\">\n    <value>tp_mouse_action</value>\n  </data>\n  <data name=\"&gt;&gt;btn_hk_ClearAndSave.Name\" xml:space=\"preserve\">\n    <value>btn_hk_ClearAndSave</value>\n  </data>\n  <data name=\"&gt;&gt;gb_storage.Name\" xml:space=\"preserve\">\n    <value>gb_storage</value>\n  </data>\n  <data name=\"btn_m4.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"&gt;&gt;btn_mouse_save.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"btn_m1.TextAlign\" type=\"System.Drawing.ContentAlignment, System.Drawing\">\n    <value>BottomCenter</value>\n  </data>\n  <data name=\"MT_Logs.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>8, 14, 8, 9</value>\n  </data>\n  <data name=\"&gt;&gt;panel_mask.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Panel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_hk_key.Items7\" xml:space=\"preserve\">\n    <value>D7</value>\n  </data>\n  <data name=\"&gt;&gt;tv_keyboard.Name\" xml:space=\"preserve\">\n    <value>tv_keyboard</value>\n  </data>\n  <data name=\"mainTabs.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>0, 0</value>\n  </data>\n  <data name=\"panel_UI.AutoScroll\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"&gt;&gt;lb_mouse_action.Name\" xml:space=\"preserve\">\n    <value>lb_mouse_action</value>\n  </data>\n  <data name=\"lb_Copyright.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>65, 17</value>\n  </data>\n  <data name=\"llb_Company.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 0, 2, 0</value>\n  </data>\n  <data name=\"&gt;&gt;btn_RuleClone.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"MT_UI.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"gb_DesktopArrangement.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>11, 14</value>\n  </data>\n  <data name=\"cb_hk_ctrl.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>1</value>\n  </data>\n  <data name=\"&gt;&gt;chb_showVDIndexOnTrayIcon.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;panel_Pages.ZOrder\" xml:space=\"preserve\">\n    <value>4</value>\n  </data>\n  <data name=\"lb_RunOnStartup.Text\" xml:space=\"preserve\">\n    <value>Note: more details such as delay of start can be set in</value>\n  </data>\n  <data name=\"&gt;&gt;lv_Plugins.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ListView, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"lb_hk_extra.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>12, 18</value>\n  </data>\n  <data name=\"chb_RunOnStartup.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>22, 26</value>\n  </data>\n  <data name=\"btn_m2.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>272, 236</value>\n  </data>\n  <metadata name=\"$this.Localizable\" type=\"System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>True</value>\n  </metadata>\n  <metadata name=\"logCMS.TrayLocation\" type=\"System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n    <value>174, 17</value>\n  </metadata>\n  <metadata name=\"ts_PageNav.TrayLocation\" type=\"System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n    <value>305, 17</value>\n  </metadata>\n  <metadata name=\"mainStatusStrip.TrayLocation\" type=\"System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n    <value>469, 17</value>\n  </metadata>\n  <metadata name=\"mainMenu.TrayLocation\" type=\"System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n    <value>17, 17</value>\n  </metadata>\n</root>"
  },
  {
    "path": "WinForms/AppController/AppController.rules.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Collections.Generic;\nusing System.Text.Json;\nusing System.Windows.Forms;\nusing VirtualSpace.Config.Events.Entity;\nusing VirtualSpace.Config.Events.Expression;\nusing ConfigManager = VirtualSpace.Config.Manager;\n\nnamespace VirtualSpace\n{\n    public partial class AppController\n    {\n        private static bool _handleItemCheck = false;\n\n        private void InitRuleListView()\n        {\n            ///////////////////////////////////////\n            // fix no ColumnHeader name issue\n            lvc_Name.Name = nameof( lvc_Name );\n            lvc_Created.Name = nameof( lvc_Created );\n            lvc_Updated.Name = nameof( lvc_Updated );\n\n            lv_Rules.ItemCheck += lv_Rules_ItemCheck;\n        }\n\n        private void ReadRules()\n        {\n            var profiles = ConfigManager.Configs.Profiles;\n            cb_RuleProfiles.Items.Clear();\n            foreach ( var profile in profiles )\n            {\n                cb_RuleProfiles.Items.Add( profile.Key );\n            }\n\n            cb_RuleProfiles.SelectedItem = ConfigManager.Configs.CurrentProfileName;\n\n            var rules = Conditions.FetchRules();\n\n            _handleItemCheck = false;\n            lv_Rules.Items.Clear();\n            foreach ( var rule in rules )\n            {\n                var item = LviByRule( rule );\n                lv_Rules.Items.Add( item );\n            }\n        }\n\n        public static void UpdateRuleListView( int index, RuleTemplate rule, List<RuleTemplate> rules )\n        {\n            _handleItemCheck = false;\n            if ( index == -1 )\n            {\n                AddRule( rule );\n            }\n            else\n            {\n                UpdateRule( index, rule );\n            }\n\n            _handleItemCheck = true;\n\n            Conditions.SaveRules( rules );\n        }\n\n        private static void AddRule( RuleTemplate rule )\n        {\n            _instance.lv_Rules.Items.Add( LviByRule( rule ) );\n        }\n\n        private static void UpdateRule( int index, RuleTemplate rule )\n        {\n            _instance.lv_Rules.Items[index] = LviByRule( rule );\n        }\n\n        private static ListViewItem LviByRule( RuleTemplate rule )\n        {\n            var item = new ListViewItem( rule.Name );\n            item.SubItems.Add( $\"{rule.Created:yyyy-MM-dd HH:mm:ss}\" );\n            item.SubItems.Add( $\"{rule.Updated:yyyy-MM-dd HH:mm:ss}\" );\n            item.SubItems.Add( rule.Id.ToString() );\n            item.Checked = rule.Enabled;\n            return item;\n        }\n\n        private void btn_RuleNew_Click( object sender, EventArgs e )\n        {\n            OpenRuleDialog();\n        }\n\n        private void btn_RuleEdit_Click( object sender, EventArgs e )\n        {\n            if ( lv_Rules.SelectedItems.Count == 0 ) return;\n            var selectedIndex = lv_Rules.SelectedIndices[0];\n            OpenRuleDialog( selectedIndex );\n        }\n\n        private void btn_RuleClone_Click( object sender, EventArgs e )\n        {\n            if ( lv_Rules.SelectedItems.Count == 0 ) return;\n\n            var rules = Conditions.FetchRules();\n            if ( rules.Count == 0 ) return;\n\n            var rule = rules[lv_Rules.SelectedIndices[0]];\n            var time = DateTime.Now;\n\n            var et = RefreshRuleId( Conditions.ParseExpressionTemplate( rule.Expression ) );\n\n            var clone = new RuleTemplate\n            {\n                Name = rule.Name,\n                Expression = JsonDocument.Parse( JsonSerializer.Serialize( et, Conditions.GetJsonSerializerOptions() ) ),\n                Enabled = rule.Enabled,\n                Action = rule.Action,\n                Created = time,\n                Updated = time\n            };\n            rules.Add( clone );\n            _handleItemCheck = false;\n            lv_Rules.Items.Add( LviByRule( clone ) );\n            _handleItemCheck = true;\n            Conditions.SaveRules( rules );\n        }\n\n        private void btn_RuleRemove_Click( object sender, EventArgs e )\n        {\n            DeleteSelectedItem();\n        }\n\n        private void DeleteSelectedItem()\n        {\n            if ( lv_Rules.SelectedItems.Count == 0 ) return;\n\n            var rules = Conditions.FetchRules();\n            if ( rules.Count == 0 ) return;\n\n            rules.RemoveAt( lv_Rules.SelectedIndices[0] );\n            lv_Rules.Items.RemoveAt( lv_Rules.SelectedIndices[0] );\n            Conditions.SaveRules( rules );\n        }\n\n        private void OpenRuleDialog( int index = -1 )\n        {\n            var ruleForm = new RuleForm( index );\n            ruleForm.Init();\n            ruleForm.TopMost = true;\n            ruleForm.ShowDialog();\n        }\n\n        private void lv_Rules_SelectedIndexChanged( object sender, EventArgs e )\n        {\n            if ( lv_Rules.SelectedItems.Count > 0 )\n            {\n                btn_RuleEdit.Enabled = true;\n                btn_RuleClone.Enabled = true;\n                btn_RuleRemove.Enabled = true;\n            }\n            else\n            {\n                btn_RuleEdit.Enabled = false;\n                btn_RuleClone.Enabled = false;\n                btn_RuleRemove.Enabled = false;\n            }\n        }\n\n        private void lv_Rules_ItemCheck( object? sender, ItemCheckEventArgs e )\n        {\n            if ( !_handleItemCheck ) return;\n            var rules = Conditions.FetchRules();\n            if ( rules.Count == 0 ) return;\n\n            var index = e.Index;\n            rules[index].Enabled = e.NewValue == CheckState.Checked;\n            Conditions.SaveRules( rules );\n        }\n\n        private void lv_Rules_VisibleChanged( object sender, EventArgs e )\n        {\n            _handleItemCheck = false;\n            _handleItemCheck = true;\n        }\n\n        private static ExpressionTemplate RefreshRuleId( ExpressionTemplate expressionTemplate )\n        {\n            expressionTemplate.id = Guid.NewGuid();\n            if ( expressionTemplate.rules == null ) return expressionTemplate;\n\n            foreach ( var rule in expressionTemplate.rules )\n            {\n                rule.id = Guid.NewGuid();\n                if ( rule.rules != null ) RefreshRuleId( rule );\n            }\n\n            return expressionTemplate;\n        }\n\n        private void lv_Rules_KeyDown( object sender, KeyEventArgs e )\n        {\n            if ( Keys.Delete != e.KeyCode ) return;\n            DeleteSelectedItem();\n        }\n\n        private void llb_goto_general_LinkClicked( object sender, LinkLabelLinkClickedEventArgs e )\n        {\n            ts_PageNavButton_Click( sender, e );\n            mainTabs.SelectTab( 0 );\n        }\n\n        public void CreateRuleFromWindowHandle( IntPtr handle )\n        {\n            var ruleForm = new RuleForm( -1 );\n            ruleForm.Init();\n            ruleForm.SetFormValuesByWindow( handle );\n            ruleForm.TopMost = true;\n            ruleForm.ShowDialog();\n        }\n    }\n}"
  },
  {
    "path": "WinForms/AppController/AppController.ui.cs",
    "content": "﻿// Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n// \n// This file is part of VirtualSpace.\n// \n// VirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n// \n// VirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n// \n// You should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n\nusing System;\nusing ConfigManager = VirtualSpace.Config.Manager;\n\nnamespace VirtualSpace\n{\n    public partial class AppController\n    {\n        private void InitUiConfig( bool resetEventHandlers = true )\n        {\n            var ui = ConfigManager.CurrentProfile.UI;\n            if ( resetEventHandlers )\n            {\n                chb_show_vd_name.CheckedChanged -= chb_show_vd_name_CheckedChanged;\n                chb_show_vd_index.CheckedChanged -= chb_show_vd_index_CheckedChanged;\n                rb_vd_index_0.CheckedChanged -= rb_vd_index_0_CheckedChanged;\n            }\n\n            chb_show_vd_name.Checked = ui.ShowVdName;\n            chb_show_vd_index.Checked = ui.ShowVdIndex;\n\n            if ( ui.ShowVdIndexType == 0 )\n            {\n                rb_vd_index_0.Checked = true;\n            }\n            else\n            {\n                rb_vd_index_1.Checked = true;\n            }\n\n            if ( resetEventHandlers )\n            {\n                chb_show_vd_name.CheckedChanged += chb_show_vd_name_CheckedChanged;\n                chb_show_vd_index.CheckedChanged += chb_show_vd_index_CheckedChanged;\n                rb_vd_index_0.CheckedChanged += rb_vd_index_0_CheckedChanged;\n            }\n        }\n\n        private void chb_show_vd_name_CheckedChanged( object? sender, EventArgs e )\n        {\n            ConfigManager.CurrentProfile.UI.ShowVdName = chb_show_vd_name.Checked;\n            ConfigManager.Save( reason: ConfigManager.CurrentProfile.UI.ShowVdName );\n        }\n\n        private void chb_show_vd_index_CheckedChanged( object? sender, EventArgs e )\n        {\n            ConfigManager.CurrentProfile.UI.ShowVdIndex = chb_show_vd_index.Checked;\n            ConfigManager.Save( reason: ConfigManager.CurrentProfile.UI.ShowVdIndex );\n        }\n\n        private void rb_vd_index_0_CheckedChanged( object? sender, EventArgs e )\n        {\n            ConfigManager.CurrentProfile.UI.ShowVdIndexType = (byte)( rb_vd_index_0.Checked ? 0 : 1 );\n            ConfigManager.Save( reason: ConfigManager.CurrentProfile.UI.ShowVdIndexType );\n        }\n    }\n}"
  },
  {
    "path": "WinForms/AppController/AppController.zh-Hans.resx",
    "content": "﻿<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <assembly alias=\"System.Drawing\" name=\"System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\" />\n  <data name=\"fileToolStripMenuItem.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>44, 21</value>\n  </data>\n  <data name=\"fileToolStripMenuItem.Text\" xml:space=\"preserve\">\n    <value>文件</value>\n  </data>\n  <data name=\"optionsToolStripMenuItem.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>44, 21</value>\n  </data>\n  <data name=\"optionsToolStripMenuItem.Text\" xml:space=\"preserve\">\n    <value>选项</value>\n  </data>\n  <data name=\"helpToolStripMenuItem.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>44, 21</value>\n  </data>\n  <data name=\"helpToolStripMenuItem.Text\" xml:space=\"preserve\">\n    <value>帮助</value>\n  </data>\n  <data name=\"closeThisWindowToolStripMenuItem.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>196, 22</value>\n  </data>\n  <data name=\"closeThisWindowToolStripMenuItem.Text\" xml:space=\"preserve\">\n    <value>关闭此窗口</value>\n  </data>\n  <data name=\"runAsAdministratorToolStripMenuItem.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>196, 22</value>\n  </data>\n  <data name=\"runAsAdministratorToolStripMenuItem.Text\" xml:space=\"preserve\">\n    <value>以管理员身份运行程序</value>\n  </data>\n  <data name=\"toolStripSeparator1.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>193, 6</value>\n  </data>\n  <data name=\"tsmiMainMenuRestart.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>196, 22</value>\n  </data>\n  <data name=\"tsmiMainMenuRestart.Text\" xml:space=\"preserve\">\n    <value>重启</value>\n  </data>\n  <data name=\"tsmiMainMenuQuit.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>196, 22</value>\n  </data>\n  <data name=\"tsmiMainMenuQuit.Text\" xml:space=\"preserve\">\n    <value>退出应用程序</value>\n  </data>\n  <data name=\"langToolStripMenuItem.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>100, 22</value>\n  </data>\n  <data name=\"langToolStripMenuItem.Text\" xml:space=\"preserve\">\n    <value>语言</value>\n  </data>\n  <data name=\"logsToolStripMenuItem.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>100, 22</value>\n  </data>\n  <data name=\"logsToolStripMenuItem.Text\" xml:space=\"preserve\">\n    <value>日志</value>\n  </data>\n  <data name=\"showLogsInGuiToolStripMenuItem.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>194, 22</value>\n  </data>\n  <data name=\"showLogsInGuiToolStripMenuItem.Text\" xml:space=\"preserve\">\n    <value>在GUI中显示完整日志</value>\n  </data>\n  <data name=\"openLogFolderToolStripMenuItem.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>194, 22</value>\n  </data>\n  <data name=\"openLogFolderToolStripMenuItem.Text\" xml:space=\"preserve\">\n    <value>打开日志文件夹...</value>\n  </data>\n  <data name=\"aboutToolStripMenuItem.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>100, 22</value>\n  </data>\n  <data name=\"aboutToolStripMenuItem.Text\" xml:space=\"preserve\">\n    <value>关于</value>\n  </data>\n  <data name=\"MT_Logs.Text\" xml:space=\"preserve\">\n    <value>日志</value>\n  </data>\n  <data name=\"logTabInfo.Text\" xml:space=\"preserve\">\n    <value>信息</value>\n  </data>\n  <data name=\"logTabDebug.Text\" xml:space=\"preserve\">\n    <value>调试</value>\n  </data>\n  <data name=\"logTabVerbose.Text\" xml:space=\"preserve\">\n    <value>详细</value>\n  </data>\n  <data name=\"logTabEvent.Text\" xml:space=\"preserve\">\n    <value>事件</value>\n  </data>\n  <data name=\"logTabWarning.Text\" xml:space=\"preserve\">\n    <value>警告</value>\n  </data>\n  <data name=\"logTabError.Text\" xml:space=\"preserve\">\n    <value>错误</value>\n  </data>\n  <data name=\"MT_General.Text\" xml:space=\"preserve\">\n    <value>通用</value>\n  </data>\n  <data name=\"tabPage_Genernal_Main.Text\" xml:space=\"preserve\">\n    <value>基本</value>\n  </data>\n  <data name=\"gb_profiles.Text\" xml:space=\"preserve\">\n    <value>配置文件</value>\n  </data>\n  <data name=\"lb_profiles_note.Text\" xml:space=\"preserve\">\n    <value>注意：快捷键绑定、鼠标动作和日志配置由所有配置文件共享。某些设置需要重启才生效。</value>\n  </data>\n  <data name=\"btn_profile_del.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>655, 25</value>\n  </data>\n  <data name=\"btn_profile_del.Text\" xml:space=\"preserve\">\n    <value>删除...</value>\n  </data>\n  <data name=\"btn_profile_rename.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>548, 25</value>\n  </data>\n  <data name=\"btn_profile_rename.Text\" xml:space=\"preserve\">\n    <value>重命名</value>\n  </data>\n  <data name=\"btn_profile_dup.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>441, 25</value>\n  </data>\n  <data name=\"btn_profile_dup.Text\" xml:space=\"preserve\">\n    <value>克隆</value>\n  </data>\n  <data name=\"gb_storage.Text\" xml:space=\"preserve\">\n    <value>存储</value>\n  </data>\n  <data name=\"lb_configRoot.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>68, 17</value>\n  </data>\n  <data name=\"lb_configRoot.Text\" xml:space=\"preserve\">\n    <value>配置文件夹</value>\n  </data>\n  <data name=\"btn_chooseConfigRoot.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>655, 22</value>\n  </data>\n  <data name=\"btn_chooseConfigRoot.Text\" xml:space=\"preserve\">\n    <value>变更...</value>\n  </data>\n  <data name=\"tb_configRoot.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>535, 23</value>\n  </data>\n  <data name=\"lb_note_configRoot.Text\" xml:space=\"preserve\">\n    <value>注意：改变配置文件夹需要重启程序。此操作仅改变位置，不会复制或移动任何文件，以免文件被意外覆盖。如果你想复用当前的配置，可以手动复制 'settings.json' 和 'Profiles' 到你选择的文件夹，然后重启程序。</value>\n  </data>\n  <data name=\"gb_general.Text\" xml:space=\"preserve\">\n    <value>通用</value>\n  </data>\n  <data name=\"llb_TaskScheduler.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>265, 59</value>\n  </data>\n  <data name=\"llb_TaskScheduler.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>80, 17</value>\n  </data>\n  <data name=\"llb_TaskScheduler.Text\" xml:space=\"preserve\">\n    <value>任务计划程序</value>\n  </data>\n  <data name=\"lb_RunOnStartup.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>212, 17</value>\n  </data>\n  <data name=\"lb_RunOnStartup.Text\" xml:space=\"preserve\">\n    <value>注意：诸如启动延迟等细节可在此设置</value>\n  </data>\n  <data name=\"chb_RunOnStartup.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>87, 21</value>\n  </data>\n  <data name=\"chb_RunOnStartup.Text\" xml:space=\"preserve\">\n    <value>随系统启动</value>\n  </data>\n  <data name=\"gb_nav.Text\" xml:space=\"preserve\">\n    <value>导航</value>\n  </data>\n  <data name=\"lb_nav_circle_h_type.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>284, 17</value>\n  </data>\n  <data name=\"lb_nav_circle_h_type.Text\" xml:space=\"preserve\">\n    <value>导航到某个方向的边界时，继续在该方向上导航将：</value>\n  </data>\n  <data name=\"cb_nav_circle_h_type.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>529, 24</value>\n  </data>\n  <data name=\"cb_nav_circle_v.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>155, 21</value>\n  </data>\n  <data name=\"cb_nav_circle_v.Text\" xml:space=\"preserve\">\n    <value>垂直方向循环(仅相同列)</value>\n  </data>\n  <data name=\"cb_nav_circle_h.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>99, 21</value>\n  </data>\n  <data name=\"cb_nav_circle_h.Text\" xml:space=\"preserve\">\n    <value>水平方向循环</value>\n  </data>\n  <data name=\"gb_Cluster.Text\" xml:space=\"preserve\">\n    <value>杂项</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_2.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>688, 76</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_2.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>85, 21</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_2.Text\" xml:space=\"preserve\">\n    <value>高对比度 2</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_1.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>564, 76</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_1.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>85, 21</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_1.Text\" xml:space=\"preserve\">\n    <value>高对比度 1</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_0.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>451, 76</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_0.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>74, 21</value>\n  </data>\n  <data name=\"rb_vdi_on_tray_style_0.Text\" xml:space=\"preserve\">\n    <value>默认样式</value>\n  </data>\n  <data name=\"chb_HideOnStart.Text\" xml:space=\"preserve\">\n    <value>程序启动时不显示主视图。</value>\n  </data>\n  <data name=\"chb_showVDIndexOnTrayIcon.Text\" xml:space=\"preserve\">\n    <value>在系统托盘图标上显示桌面索引。</value>\n  </data>\n  <data name=\"chb_notify_vd_changed.Text\" xml:space=\"preserve\">\n    <value>切换虚拟桌面时显示通知。</value>\n  </data>\n  <data name=\"chb_HideMainViewIfItsShown.Text\" xml:space=\"preserve\">\n    <value>当使用热键唤起主视图时，如果主视图已经显示，则关闭之。</value>\n  </data>\n  <data name=\"tabPage_Genernal_Keyboard.Text\" xml:space=\"preserve\">\n    <value>键盘</value>\n  </data>\n  <data name=\"tp_hk_main.Text\" xml:space=\"preserve\">\n    <value>热键绑定</value>\n  </data>\n  <data name=\"btn_hk_ClearAndSave.Text\" xml:space=\"preserve\">\n    <value>清除并保存</value>\n  </data>\n  <data name=\"btn_hk_RegAndSave.Text\" xml:space=\"preserve\">\n    <value>注册并保存</value>\n  </data>\n  <data name=\"tp_hk_extra.Text\" xml:space=\"preserve\">\n    <value>备用</value>\n  </data>\n  <data name=\"tv_keyboard.Nodes\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n    <value>\n        AAEAAAD/////AQAAAAAAAAAMAgAAAEZTeXN0ZW0uV2luZG93cy5Gb3JtcywgQ3VsdHVyZT1uZXV0cmFs\n        LCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAdU3lzdGVtLldpbmRvd3MuRm9ybXMu\n        VHJlZU5vZGUOAAAABFRleHQLVG9vbFRpcFRleHQETmFtZQlJc0NoZWNrZWQKSW1hZ2VJbmRleAhJbWFn\n        ZUtleRJTZWxlY3RlZEltYWdlSW5kZXgQU2VsZWN0ZWRJbWFnZUtleQpDaGlsZENvdW50CWNoaWxkcmVu\n        MAljaGlsZHJlbjEJY2hpbGRyZW4yCWNoaWxkcmVuMwljaGlsZHJlbjQBAQEAAAEAAQAEBAQEBAEICAgd\n        U3lzdGVtLldpbmRvd3MuRm9ybXMuVHJlZU5vZGUCAAAAHVN5c3RlbS5XaW5kb3dzLkZvcm1zLlRyZWVO\n        b2RlAgAAAB1TeXN0ZW0uV2luZG93cy5Gb3Jtcy5UcmVlTm9kZQIAAAAdU3lzdGVtLldpbmRvd3MuRm9y\n        bXMuVHJlZU5vZGUCAAAAHVN5c3RlbS5XaW5kb3dzLkZvcm1zLlRyZWVOb2RlAgAAAAIAAAAGAwAAAAbp\n        gJrnlKgGBAAAAAAGBQAAAA9oa19yb290X2dlbmVyYWwA/////wkEAAAA/////wkEAAAABQAAAAkHAAAA\n        CQgAAAAJCQAAAAkKAAAACQsAAAAFBwAAAB1TeXN0ZW0uV2luZG93cy5Gb3Jtcy5UcmVlTm9kZQkAAAAE\n        VGV4dAtUb29sVGlwVGV4dAROYW1lCUlzQ2hlY2tlZApJbWFnZUluZGV4CEltYWdlS2V5ElNlbGVjdGVk\n        SW1hZ2VJbmRleBBTZWxlY3RlZEltYWdlS2V5CkNoaWxkQ291bnQBAQEAAAEAAQABCAgIAgAAAAYMAAAA\n        D+WUpOi1t+S4u+inhuWbvgkEAAAABg4AAAAVaGtfbm9kZV9yaXNlX21haW52aWV3AP////8JBAAAAP//\n        //8JBAAAAAAAAAAFCAAAAB1TeXN0ZW0uV2luZG93cy5Gb3Jtcy5UcmVlTm9kZQkAAAAEVGV4dAtUb29s\n        VGlwVGV4dAROYW1lCUlzQ2hlY2tlZApJbWFnZUluZGV4CEltYWdlS2V5ElNlbGVjdGVkSW1hZ2VJbmRl\n        eBBTZWxlY3RlZEltYWdlS2V5CkNoaWxkQ291bnQBAQEAAAEAAQABCAgIAgAAAAYQAAAAEuaJk+W8gOeo\n        i+W6j+aOp+WItgkEAAAABhIAAAAbaGtfbm9kZV9vcGVuX2FwcF9jb250cm9sbGVyAP////8JBAAAAP//\n        //8JBAAAAAAAAAAFCQAAAB1TeXN0ZW0uV2luZG93cy5Gb3Jtcy5UcmVlTm9kZQkAAAAEVGV4dAtUb29s\n        VGlwVGV4dAROYW1lCUlzQ2hlY2tlZApJbWFnZUluZGV4CEltYWdlS2V5ElNlbGVjdGVkSW1hZ2VJbmRl\n        eBBTZWxlY3RlZEltYWdlS2V5CkNoaWxkQ291bnQBAQEAAAEAAQABCAgIAgAAAAYUAAAAJOS4uuW9k+WJ\n        jea0u+WKqOeoi+W6j+WUpOi1t+S4u+inhuWbvgkEAAAABhYAAAAkaGtfbm9kZV9yaXNlX21haW52aWV3\n        X2Zvcl9hY3RpdmVfYXBwAP////8JBAAAAP////8JBAAAAAAAAAAFCgAAAB1TeXN0ZW0uV2luZG93cy5G\n        b3Jtcy5UcmVlTm9kZQkAAAAEVGV4dAtUb29sVGlwVGV4dAROYW1lCUlzQ2hlY2tlZApJbWFnZUluZGV4\n        CEltYWdlS2V5ElNlbGVjdGVkSW1hZ2VJbmRleBBTZWxlY3RlZEltYWdlS2V5CkNoaWxkQ291bnQBAQEA\n        AAEAAQABCAgIAgAAAAYYAAAAHuS4uuW9k+WJjeahjOmdouWUpOi1t+S4u+inhuWbvgkEAAAABhoAAAAk\n        aGtfbm9kZV9yaXNlX21haW52aWV3X2Zvcl9jdXJyZW50X3ZkAP////8JBAAAAP////8JBAAAAAAAAAAF\n        CwAAAB1TeXN0ZW0uV2luZG93cy5Gb3Jtcy5UcmVlTm9kZQkAAAAEVGV4dAtUb29sVGlwVGV4dAROYW1l\n        CUlzQ2hlY2tlZApJbWFnZUluZGV4CEltYWdlS2V5ElNlbGVjdGVkSW1hZ2VJbmRleBBTZWxlY3RlZElt\n        YWdlS2V5CkNoaWxkQ291bnQBAQEAAAEAAQABCAgIAgAAAAYcAAAAMOS4uuW9k+WJjeahjOmdouS4reea\n        hOa0u+WKqOeoi+W6j+WUpOi1t+S4u+inhuWbvgkEAAAABh4AAAAyaGtfbm9kZV9yaXNlX21haW52aWV3\n        X2Zvcl9hY3RpdmVfYXBwX2luX2N1cnJlbnRfdmQA/////wkEAAAA/////wkEAAAAAAAAAAs=\n</value>\n  </data>\n  <data name=\"tv_keyboard.Nodes1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n    <value>\n        AAEAAAD/////AQAAAAAAAAAMAgAAAEZTeXN0ZW0uV2luZG93cy5Gb3JtcywgQ3VsdHVyZT1uZXV0cmFs\n        LCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAdU3lzdGVtLldpbmRvd3MuRm9ybXMu\n        VHJlZU5vZGULAAAABFRleHQLVG9vbFRpcFRleHQETmFtZQlJc0NoZWNrZWQKSW1hZ2VJbmRleAhJbWFn\n        ZUtleRJTZWxlY3RlZEltYWdlSW5kZXgQU2VsZWN0ZWRJbWFnZUtleQpDaGlsZENvdW50CWNoaWxkcmVu\n        MAljaGlsZHJlbjEBAQEAAAEAAQAEBAEICAgdU3lzdGVtLldpbmRvd3MuRm9ybXMuVHJlZU5vZGUCAAAA\n        HVN5c3RlbS5XaW5kb3dzLkZvcm1zLlRyZWVOb2RlAgAAAAIAAAAGAwAAAAbmoYzpnaIGBAAAAAAGBQAA\n        AA9oa19yb290X2Rlc2t0b3AA/////wkEAAAA/////wkEAAAAAgAAAAkHAAAACQgAAAAFBwAAAB1TeXN0\n        ZW0uV2luZG93cy5Gb3Jtcy5UcmVlTm9kZQkAAAAEVGV4dAtUb29sVGlwVGV4dAROYW1lCUlzQ2hlY2tl\n        ZApJbWFnZUluZGV4CEltYWdlS2V5ElNlbGVjdGVkSW1hZ2VJbmRleBBTZWxlY3RlZEltYWdlS2V5CkNo\n        aWxkQ291bnQBAQEAAAEAAQABCAgIAgAAAAYJAAAABuWIh+aNogkEAAAABgsAAAANaGtfcGFyZW50X3N2\n        ZAD/////CQQAAAD/////CQQAAAAAAAAABQgAAAAdU3lzdGVtLldpbmRvd3MuRm9ybXMuVHJlZU5vZGUN\n        AAAABFRleHQLVG9vbFRpcFRleHQETmFtZQlJc0NoZWNrZWQKSW1hZ2VJbmRleAhJbWFnZUtleRJTZWxl\n        Y3RlZEltYWdlSW5kZXgQU2VsZWN0ZWRJbWFnZUtleQpDaGlsZENvdW50CWNoaWxkcmVuMAljaGlsZHJl\n        bjEJY2hpbGRyZW4yCWNoaWxkcmVuMwEBAQAAAQABAAQEBAQBCAgIHVN5c3RlbS5XaW5kb3dzLkZvcm1z\n        LlRyZWVOb2RlAgAAAB1TeXN0ZW0uV2luZG93cy5Gb3Jtcy5UcmVlTm9kZQIAAAAdU3lzdGVtLldpbmRv\n        d3MuRm9ybXMuVHJlZU5vZGUCAAAAHVN5c3RlbS5XaW5kb3dzLkZvcm1zLlRyZWVOb2RlAgAAAAIAAAAG\n        DQAAAAblr7zoiKoJBAAAAAYPAAAAEGhrX3BhcmVudF9uYXZfdmQA/////wkEAAAA/////wkEAAAABAAA\n        AAkRAAAACRIAAAAJEwAAAAkUAAAABREAAAAdU3lzdGVtLldpbmRvd3MuRm9ybXMuVHJlZU5vZGUJAAAA\n        BFRleHQLVG9vbFRpcFRleHQETmFtZQlJc0NoZWNrZWQKSW1hZ2VJbmRleAhJbWFnZUtleRJTZWxlY3Rl\n        ZEltYWdlSW5kZXgQU2VsZWN0ZWRJbWFnZUtleQpDaGlsZENvdW50AQEBAAABAAEAAQgICAIAAAAGFQAA\n        AAblkJHlt6YJBAAAAAYXAAAAEGhrX25vZGVfbmF2X2xlZnQA/////wkEAAAA/////wkEAAAAAAAAAAUS\n        AAAAHVN5c3RlbS5XaW5kb3dzLkZvcm1zLlRyZWVOb2RlCQAAAARUZXh0C1Rvb2xUaXBUZXh0BE5hbWUJ\n        SXNDaGVja2VkCkltYWdlSW5kZXgISW1hZ2VLZXkSU2VsZWN0ZWRJbWFnZUluZGV4EFNlbGVjdGVkSW1h\n        Z2VLZXkKQ2hpbGRDb3VudAEBAQAAAQABAAEICAgCAAAABhkAAAAG5ZCR5Y+zCQQAAAAGGwAAABFoa19u\n        b2RlX25hdl9yaWdodAD/////CQQAAAD/////CQQAAAAAAAAABRMAAAAdU3lzdGVtLldpbmRvd3MuRm9y\n        bXMuVHJlZU5vZGUJAAAABFRleHQLVG9vbFRpcFRleHQETmFtZQlJc0NoZWNrZWQKSW1hZ2VJbmRleAhJ\n        bWFnZUtleRJTZWxlY3RlZEltYWdlSW5kZXgQU2VsZWN0ZWRJbWFnZUtleQpDaGlsZENvdW50AQEBAAAB\n        AAEAAQgICAIAAAAGHQAAAAblkJHkuIoJBAAAAAYfAAAADmhrX25vZGVfbmF2X3VwAP////8JBAAAAP//\n        //8JBAAAAAAAAAAFFAAAAB1TeXN0ZW0uV2luZG93cy5Gb3Jtcy5UcmVlTm9kZQkAAAAEVGV4dAtUb29s\n        VGlwVGV4dAROYW1lCUlzQ2hlY2tlZApJbWFnZUluZGV4CEltYWdlS2V5ElNlbGVjdGVkSW1hZ2VJbmRl\n        eBBTZWxlY3RlZEltYWdlS2V5CkNoaWxkQ291bnQBAQEAAAEAAQABCAgIAgAAAAYhAAAABuWQkeS4iwkE\n        AAAABiMAAAAQaGtfbm9kZV9uYXZfZG93bgD/////CQQAAAD/////CQQAAAAAAAAACw==\n</value>\n  </data>\n  <data name=\"tv_keyboard.Nodes2\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n    <value>\n        AAEAAAD/////AQAAAAAAAAAMAgAAAEZTeXN0ZW0uV2luZG93cy5Gb3JtcywgQ3VsdHVyZT1uZXV0cmFs\n        LCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAdU3lzdGVtLldpbmRvd3MuRm9ybXMu\n        VHJlZU5vZGULAAAABFRleHQLVG9vbFRpcFRleHQETmFtZQlJc0NoZWNrZWQKSW1hZ2VJbmRleAhJbWFn\n        ZUtleRJTZWxlY3RlZEltYWdlSW5kZXgQU2VsZWN0ZWRJbWFnZUtleQpDaGlsZENvdW50CWNoaWxkcmVu\n        MAljaGlsZHJlbjEBAQEAAAEAAQAEBAEICAgdU3lzdGVtLldpbmRvd3MuRm9ybXMuVHJlZU5vZGUCAAAA\n        HVN5c3RlbS5XaW5kb3dzLkZvcm1zLlRyZWVOb2RlAgAAAAIAAAAGAwAAAAbnqpflj6MGBAAAAAAGBQAA\n        AA5oa19yb290X3dpbmRvdwD/////CQQAAAD/////CQQAAAACAAAACQcAAAAJCAAAAAUHAAAAHVN5c3Rl\n        bS5XaW5kb3dzLkZvcm1zLlRyZWVOb2RlCQAAAARUZXh0C1Rvb2xUaXBUZXh0BE5hbWUJSXNDaGVja2Vk\n        CkltYWdlSW5kZXgISW1hZ2VLZXkSU2VsZWN0ZWRJbWFnZUluZGV4EFNlbGVjdGVkSW1hZ2VLZXkKQ2hp\n        bGRDb3VudAEBAQAAAQABAAEICAgCAAAABgkAAAAG56e75YqoCQQAAAAGCwAAABJoa19wYXJlbnRfd2lu\n        X21vdmUA/////wkEAAAA/////wkEAAAAAAAAAAUIAAAAHVN5c3RlbS5XaW5kb3dzLkZvcm1zLlRyZWVO\n        b2RlCQAAAARUZXh0C1Rvb2xUaXBUZXh0BE5hbWUJSXNDaGVja2VkCkltYWdlSW5kZXgISW1hZ2VLZXkS\n        U2VsZWN0ZWRJbWFnZUluZGV4EFNlbGVjdGVkSW1hZ2VLZXkKQ2hpbGRDb3VudAEBAQAAAQABAAEICAgC\n        AAAABg0AAAAP56e75Yqo5bm26Lef6ZqPCQQAAAAGDwAAABloa19wYXJlbnRfd2luX21vdmVfZm9sbG93\n        AP////8JBAAAAP////8JBAAAAAAAAAAL\n</value>\n  </data>\n  <data name=\"tabPage_Genernal_Mouse.Text\" xml:space=\"preserve\">\n    <value>鼠标</value>\n  </data>\n  <data name=\"lb_MouseOnTaskbarSwitchDesktop2.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>398, 17</value>\n  </data>\n  <data name=\"lb_MouseOnTaskbarSwitchDesktop2.Text\" xml:space=\"preserve\">\n    <value>下滚 =&gt; 导航到右侧桌面                    SHIFT+下滚 =&gt; 导航到下面桌面</value>\n  </data>\n  <data name=\"tv_mouse.Nodes\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n    <value>\n        AAEAAAD/////AQAAAAAAAAAMAgAAAEZTeXN0ZW0uV2luZG93cy5Gb3JtcywgQ3VsdHVyZT1uZXV0cmFs\n        LCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAdU3lzdGVtLldpbmRvd3MuRm9ybXMu\n        VHJlZU5vZGULAAAABFRleHQLVG9vbFRpcFRleHQETmFtZQlJc0NoZWNrZWQKSW1hZ2VJbmRleAhJbWFn\n        ZUtleRJTZWxlY3RlZEltYWdlSW5kZXgQU2VsZWN0ZWRJbWFnZUtleQpDaGlsZENvdW50CWNoaWxkcmVu\n        MAljaGlsZHJlbjEBAQEAAAEAAQAEBAEICAgdU3lzdGVtLldpbmRvd3MuRm9ybXMuVHJlZU5vZGUCAAAA\n        HVN5c3RlbS5XaW5kb3dzLkZvcm1zLlRyZWVOb2RlAgAAAAIAAAAGAwAAAAnkuLvop4blm74GBAAAAAAG\n        BQAAABNtb3VzZV9yb290X21haW52aWV3AP////8JBAAAAP////8JBAAAAAIAAAAJBwAAAAkIAAAABQcA\n        AAAdU3lzdGVtLldpbmRvd3MuRm9ybXMuVHJlZU5vZGUJAAAABFRleHQLVG9vbFRpcFRleHQETmFtZQlJ\n        c0NoZWNrZWQKSW1hZ2VJbmRleAhJbWFnZUtleRJTZWxlY3RlZEltYWdlSW5kZXgQU2VsZWN0ZWRJbWFn\n        ZUtleQpDaGlsZENvdW50AQEBAAABAAEAAQgICAIAAAAGCQAAAAbmoYzpnaIJBAAAAAYLAAAAFG1vdXNl\n        X3BhcmVudF9kZXNrdG9wAP////8JBAAAAP////8JBAAAAAAAAAAFCAAAAB1TeXN0ZW0uV2luZG93cy5G\n        b3Jtcy5UcmVlTm9kZQkAAAAEVGV4dAtUb29sVGlwVGV4dAROYW1lCUlzQ2hlY2tlZApJbWFnZUluZGV4\n        CEltYWdlS2V5ElNlbGVjdGVkSW1hZ2VJbmRleBBTZWxlY3RlZEltYWdlS2V5CkNoaWxkQ291bnQBAQEA\n        AAEAAQABCAgIAgAAAAYNAAAABueql+WPowkEAAAABg8AAAATbW91c2VfcGFyZW50X3dpbmRvdwD/////\n        CQQAAAD/////CQQAAAAAAAAACw==\n</value>\n  </data>\n  <data name=\"lb_MouseOnTaskbarSwitchDesktop1.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>398, 17</value>\n  </data>\n  <data name=\"lb_MouseOnTaskbarSwitchDesktop1.Text\" xml:space=\"preserve\">\n    <value>上滚 =&gt; 导航到左侧桌面                    SHIFT+上滚 =&gt; 导航到上面桌面</value>\n  </data>\n  <data name=\"tp_mouse_action.Text\" xml:space=\"preserve\">\n    <value>动作</value>\n  </data>\n  <data name=\"btn_mouse_save.Text\" xml:space=\"preserve\">\n    <value>保存</value>\n  </data>\n  <data name=\"chb_MouseOnTaskbarSwitchDesktop.Text\" xml:space=\"preserve\">\n    <value>当鼠标指针在任务栏上时，用滚轮切换虚拟桌面。</value>\n  </data>\n  <data name=\"MT_UI.Text\" xml:space=\"preserve\">\n    <value>界面</value>\n  </data>\n  <data name=\"lb_ui_vd_view.Text\" xml:space=\"preserve\">\n    <value>虚拟桌面视图</value>\n  </data>\n  <data name=\"rb_vd_index_1.Text\" xml:space=\"preserve\">\n    <value>1-基索引</value>\n  </data>\n  <data name=\"rb_vd_index_0.Text\" xml:space=\"preserve\">\n    <value>0-基索引</value>\n  </data>\n  <data name=\"chb_show_vd_index.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>123, 21</value>\n  </data>\n  <data name=\"chb_show_vd_index.Text\" xml:space=\"preserve\">\n    <value>显示虚拟桌面索引</value>\n  </data>\n  <data name=\"chb_show_vd_name.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>123, 21</value>\n  </data>\n  <data name=\"chb_show_vd_name.Text\" xml:space=\"preserve\">\n    <value>显示虚拟桌面名称</value>\n  </data>\n  <data name=\"gb_DesktopArrangement.Text\" xml:space=\"preserve\">\n    <value>虚拟桌面摆放方式</value>\n  </data>\n  <data name=\"btn_m7.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n</value>\n  </data>\n  <data name=\"btn_m7.Text\" xml:space=\"preserve\">\n    <value>右下 ↖ 左上, 纵向</value>\n  </data>\n  <data name=\"btn_m6.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n        aHy4C99++gc4d8SX26+Q+QAAAABJRU5ErkJggg==\n</value>\n  </data>\n  <data name=\"btn_m6.Text\" xml:space=\"preserve\">\n    <value>左下 ↗ 右上, 纵向</value>\n  </data>\n  <data name=\"btn_m5.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n</value>\n  </data>\n  <data name=\"btn_m5.Text\" xml:space=\"preserve\">\n    <value>右上 ↙ 左下, 纵向</value>\n  </data>\n  <data name=\"btn_m4.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n</value>\n  </data>\n  <data name=\"btn_m4.Text\" xml:space=\"preserve\">\n    <value>左上 ↘ 右下, 纵向(列满换列)</value>\n  </data>\n  <data name=\"btn_m3.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n        QmCC\n</value>\n  </data>\n  <data name=\"btn_m3.Text\" xml:space=\"preserve\">\n    <value>右下 ↖ 左上, 横向</value>\n  </data>\n  <data name=\"btn_m2.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n        D2i8eBd+fvoXWkqEydvScvcAAAAASUVORK5CYII=\n</value>\n  </data>\n  <data name=\"btn_m2.Text\" xml:space=\"preserve\">\n    <value>左下 ↗ 右上, 横向</value>\n  </data>\n  <data name=\"btn_m1.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n</value>\n  </data>\n  <data name=\"btn_m1.Text\" xml:space=\"preserve\">\n    <value>右上 ↙ 左下, 横向</value>\n  </data>\n  <data name=\"btn_m0.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n</value>\n  </data>\n  <data name=\"btn_m0.Text\" xml:space=\"preserve\">\n    <value>左上 ↘ 右下, 横向(行满换行)</value>\n  </data>\n  <data name=\"lb_DesktopArrangementNote.Text\" xml:space=\"preserve\">\n    <value>注意：当且仅当虚拟桌面的数量是自然数[1,n]的2次方时，才可以变换摆放方式；条件不满足时程序将自动重置为第一种摆放方式。</value>\n  </data>\n  <data name=\"MT_Rules.Text\" xml:space=\"preserve\">\n    <value>规则</value>\n  </data>\n  <data name=\"gb_Rules.Text\" xml:space=\"preserve\">\n    <value>规则列表</value>\n  </data>\n  <data name=\"lvc_Name.Text\" xml:space=\"preserve\">\n    <value>名称</value>\n  </data>\n  <data name=\"lvc_Created.Text\" xml:space=\"preserve\">\n    <value>创建时间</value>\n  </data>\n  <data name=\"lvc_Updated.Text\" xml:space=\"preserve\">\n    <value>更新时间</value>\n  </data>\n  <data name=\"btn_RuleEdit.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAu\n        IgAALiIBquLdkgAAAbhJREFUSEut1r8rRWEcx/EzsGBgY6EkCxnIYDFJMphMpMjAoDAZDEpmi6KwKH8D\n        m2Rh8DMhKRsZWFAkOt6f7nPufTzOee653OFV3+f7fJ/zud3TOfcGQRAWUzkO8YA+08PPof+oxAlYZHWA\n        vd/Df7UBih8+0KDNOmzhvAAXuEYJopA2fMEOkRttHjnNtDah8yu4NHUL7BkjtpmXvhqdHbF626bXa/Vk\n        Wc1Xs9Cn6U6hCzqn2r6YrEJ7Y2Z9kFkH4bNp7GQaqTSBItYcNDOMqkydC9nPNPKqxRtYJBqFdaawkDLc\n        gUWiT3TCOldYyDEovNrhnEsfomeJwst6ldjShayDwmsccWeRP2QeFF4LiDtr+EOGoD2fNWh2Ev2mdvhD\n        9OxoL4nuk+Z6zHrJrB3+kD1oL84pNMNbNtubMD2HP+QK2nPdowKa0Q2P+lOm50gO0UXeoT2bnnb9PERz\n        g4j2Cg7Re0f9yBP0FbkP2wCimbwhu7lmVjUaUWr1XPbbODHkBVThGZod+mOgAP1+16Ae7swMdF6m4QRI\n        bqAYZuEESBDegqoo9KvoBEgQtkJ/DHRv/uoRi3AuLmHwDTVanr01N1gtAAAAAElFTkSuQmCC\n</value>\n  </data>\n  <data name=\"btn_RuleEdit.Text\" xml:space=\"preserve\">\n    <value>编辑...</value>\n  </data>\n  <data name=\"btn_RuleClone.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAu\n        IgAALiIBquLdkgAAASdJREFUSEvt1j9KA0EUx/EtvIOQ2gi2Eey0srAxGARFEVG8gYUnsPAaNrmJVmlj\n        qXeQEPy//r7DezDGCWwmI1ik+Cy8md33IzOTTap6UKWcyKOM5vAsd9JOBaxKXdBDKuRQ/IYruch0K6FP\n        KmRdPCQ139S20GPsA23Zla5cC5Nf0pL4wVmcCX1GFEdWTHqTYiFjKya9S7EQloWCTaapT6JYCGeaYl+o\n        N63+kxCOHTWbvwiJLUJm8r9Clmwsx55MDTmwGh1ZznQp9PhMhcTf+HBTQ6/mw2p//iUVgr6NlXA6LQRb\n        0mvoXPxFe2Nj7MmahGb+qt9hYA4sE302orGACxPgN5ljl4NN9k9yLL9ChuJBJYQlinFZkXvhfxL7k+tJ\n        2JsfAfWgqr4BuhhlyEKF8m4AAAAASUVORK5CYII=\n</value>\n  </data>\n  <data name=\"btn_RuleClone.Text\" xml:space=\"preserve\">\n    <value>复制</value>\n  </data>\n  <data name=\"btn_RuleNew.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAu\n        IgAALiIBquLdkgAAAbVJREFUSEutlt0qBVEYhic2FyE5kJyLXISfAyIugRDiApRrUIiIe1CUwpH8lJ92\n        ckYccEJ+QlLb8+5ZZn9jz6wYvqen9lqr+d7ZzayZCYJC4LMSe3AO9/AGH/EW93EeezGHSceHJk6GjuEF\n        /oRLHMekPgkThaAedzEL+rcNGO/5baIJn/EvvGALlvqaQQ2+4X/wjrVYFpLHVNpgzdABdj2BM4yFDKKX\n        GbA1C3Y9hREsBlTgQ3HKwxTYmga7noJu90qFdLkJLxlDRI9ClqKhhwGwNQx23cOKQo6ioUMXWWdu2QJb\n        22DXRTvYPo4ThdxFQ8cxZKk82D6OO4WU7Y0NyFKbYPs4XhVyHw0dJ5ClUv7JvUKOo6FDG013j0XXwNYO\n        2HXRCbaP41Qhy9HQwyDY+sXdtaqQ7mjoQXePLZ25XffQqxDteO1MLxlDnjCnEDlUnPKQ8dk1isWAL/XU\n        TEUbbd2QcpEt5xj2jn6Ez3+9B/6DD6zDshDZjHqz/QVt7lYs9Y0NQvWO1pdIFg6xEeM9yyZKTuAV/oRr\n        nMSkPgkTcauwDxfwAPW99fXdpbNexH6sxqTjMQg+Aa1zHP0aaDh2AAAAAElFTkSuQmCC\n</value>\n  </data>\n  <data name=\"btn_RuleNew.Text\" xml:space=\"preserve\">\n    <value>新建...</value>\n  </data>\n  <data name=\"btn_RuleRemove.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAu\n        IgAALiIBquLdkgAAAWJJREFUSEvt1r1KA0EYheHF3yakSCM2NhZiwE5R0cpKRcktWHsJYiGIegmCpdgK\n        IooI4gUIXoE2AX9BMIKIlfE9w3w6yGx015RbPAl7ZuY7YQPJJs0kaaUPZ2jiHa8BXX/gHP2InXeiYeAC\n        KvjNJWLnnWjorcOG7GAEs5jz77rehu3ZQmyOeyljEANeJ+Zhh1+Qdjt0O59hexfQAZuluWVtrMM2xaik\n        8SML1yS2ZuoqSRvQLg2VVLAShHsYgu59Vjq3C5u1iord2zEfyprP8tJgmzWhzBZalSxiE+5AYBwbqAWZ\n        ZC7pwi2Un/jMHEH5A3p8JplLunEH5ac+M8dQ/ohen0lR4vKi5GuhKFH+7xL9t9xAuYZaLodQfg99GMsz\n        l8gUllENMhmG8ukgk1wlWaWWjPpQDjCDpRx0bh82S7/UrkBK0Bdoi+3wBD0/cPVNrVfQhjeEz1h/pXN6\n        FrvGJJibJJ8pRI1RloGcIgAAAABJRU5ErkJggg==\n</value>\n  </data>\n  <data name=\"btn_RuleRemove.Text\" xml:space=\"preserve\">\n    <value>删除</value>\n  </data>\n  <data name=\"gb_CurrentProfile.Text\" xml:space=\"preserve\">\n    <value>当前配置文件</value>\n  </data>\n  <data name=\"llb_goto_general.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>164, 17</value>\n  </data>\n  <data name=\"llb_goto_general.Text\" xml:space=\"preserve\">\n    <value>切换配置文件请跳转到通用页</value>\n  </data>\n  <data name=\"MT_Plugins.Text\" xml:space=\"preserve\">\n    <value>插件</value>\n  </data>\n  <data name=\"gb_Plugins.Text\" xml:space=\"preserve\">\n    <value>插件列表</value>\n  </data>\n  <data name=\"lvc_PluginName.Text\" xml:space=\"preserve\">\n    <value>名称</value>\n  </data>\n  <data name=\"lvc_PluginVersion.Text\" xml:space=\"preserve\">\n    <value>版本</value>\n  </data>\n  <data name=\"lvc_PluginAuthor.Text\" xml:space=\"preserve\">\n    <value>作者</value>\n  </data>\n  <data name=\"lvc_PluginEmail.Text\" xml:space=\"preserve\">\n    <value>邮箱</value>\n  </data>\n  <data name=\"btn_PluginSettings.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAu\n        IgAALiIBquLdkgAAAbhJREFUSEut1r8rRWEcx/EzsGBgY6EkCxnIYDFJMphMpMjAoDAZDEpmi6KwKH8D\n        m2Rh8DMhKRsZWFAkOt6f7nPufTzOee653OFV3+f7fJ/zud3TOfcGQRAWUzkO8YA+08PPof+oxAlYZHWA\n        vd/Df7UBih8+0KDNOmzhvAAXuEYJopA2fMEOkRttHjnNtDah8yu4NHUL7BkjtpmXvhqdHbF626bXa/Vk\n        Wc1Xs9Cn6U6hCzqn2r6YrEJ7Y2Z9kFkH4bNp7GQaqTSBItYcNDOMqkydC9nPNPKqxRtYJBqFdaawkDLc\n        gUWiT3TCOldYyDEovNrhnEsfomeJwst6ldjShayDwmsccWeRP2QeFF4LiDtr+EOGoD2fNWh2Ev2mdvhD\n        9OxoL4nuk+Z6zHrJrB3+kD1oL84pNMNbNtubMD2HP+QK2nPdowKa0Q2P+lOm50gO0UXeoT2bnnb9PERz\n        g4j2Cg7Re0f9yBP0FbkP2wCimbwhu7lmVjUaUWr1XPbbODHkBVThGZod+mOgAP1+16Ae7swMdF6m4QRI\n        bqAYZuEESBDegqoo9KvoBEgQtkJ/DHRv/uoRi3AuLmHwDTVanr01N1gtAAAAAElFTkSuQmCC\n</value>\n  </data>\n  <data name=\"btn_PluginSettings.Text\" xml:space=\"preserve\">\n    <value>设置</value>\n  </data>\n  <data name=\"logCMS.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>101, 26</value>\n  </data>\n  <data name=\"clearToolStripMenuItem.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>100, 22</value>\n  </data>\n  <data name=\"clearToolStripMenuItem.Text\" xml:space=\"preserve\">\n    <value>清空</value>\n  </data>\n  <data name=\"tsb_general.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n        Aoj+DyGcozUN/YRVAAAAAElFTkSuQmCC\n</value>\n  </data>\n  <data name=\"tsb_general.Text\" xml:space=\"preserve\">\n    <value>通用</value>\n  </data>\n  <data name=\"tsb_ui.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n</value>\n  </data>\n  <data name=\"tsb_ui.Text\" xml:space=\"preserve\">\n    <value>界面</value>\n  </data>\n  <data name=\"tsb_rules.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n</value>\n  </data>\n  <data name=\"tsb_rules.Text\" xml:space=\"preserve\">\n    <value>规则</value>\n  </data>\n  <data name=\"tsb_plugins.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n        AABJRU5ErkJggg==\n</value>\n  </data>\n  <data name=\"tsb_plugins.Text\" xml:space=\"preserve\">\n    <value>插件</value>\n  </data>\n  <data name=\"tsb_logs.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n        s+KxRWEAAAAASUVORK5CYII=\n</value>\n  </data>\n  <data name=\"tsb_logs.Text\" xml:space=\"preserve\">\n    <value>日志</value>\n  </data>\n  <data name=\"tsb_about.Image\" type=\"System.Drawing.Bitmap, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n    <value>\n        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\n        gg==\n</value>\n  </data>\n  <data name=\"tsb_about.Text\" xml:space=\"preserve\">\n    <value>关于</value>\n  </data>\n</root>"
  },
  {
    "path": "WinForms/AppController/RuleForm.Designer.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nnamespace VirtualSpace\n{\n    partial class RuleForm\n    {\n        /// <summary>\n        /// Required designer variable.\n        /// </summary>\n        private System.ComponentModel.IContainer components = null;\n\n        /// <summary>\n        /// Clean up any resources being used.\n        /// </summary>\n        /// <param name=\"disposing\">true if managed resources should be disposed; otherwise, false.</param>\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing && (components != null)) {\n                components.Dispose();\n            }\n            base.Dispose(disposing);\n        }\n\n        #region Windows Form Designer generated code\n\n        /// <summary>\n        /// Required method for Designer support - do not modify\n        /// the contents of this method with the code editor.\n        /// </summary>\n        private void InitializeComponent()\n        {\n            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(RuleForm));\n            gb_Basic = new System.Windows.Forms.GroupBox();\n            cb_Enabled = new System.Windows.Forms.CheckBox();\n            tb_Name = new System.Windows.Forms.TextBox();\n            lb_Name = new System.Windows.Forms.Label();\n            gb_Rules = new System.Windows.Forms.GroupBox();\n            tb_CommandLine = new System.Windows.Forms.TextBox();\n            cbb_CommandLine = new System.Windows.Forms.ComboBox();\n            cb_CommandLine = new System.Windows.Forms.CheckBox();\n            cbb_WinInScreen = new System.Windows.Forms.ComboBox();\n            cb_WinInScreen = new System.Windows.Forms.CheckBox();\n            tb_WndClass = new System.Windows.Forms.TextBox();\n            cbb_WndClass = new System.Windows.Forms.ComboBox();\n            cb_WndClass = new System.Windows.Forms.CheckBox();\n            tb_ProcessPath = new System.Windows.Forms.TextBox();\n            cbb_ProcessPath = new System.Windows.Forms.ComboBox();\n            cb_ProcessPath = new System.Windows.Forms.CheckBox();\n            tb_ProcessName = new System.Windows.Forms.TextBox();\n            cbb_ProcessName = new System.Windows.Forms.ComboBox();\n            cb_ProcessName = new System.Windows.Forms.CheckBox();\n            tb_Title = new System.Windows.Forms.TextBox();\n            cbb_Title = new System.Windows.Forms.ComboBox();\n            cb_Title = new System.Windows.Forms.CheckBox();\n            gb_Actions = new System.Windows.Forms.GroupBox();\n            cbb_MoveToScreen = new System.Windows.Forms.ComboBox();\n            cb_MoveToScreen = new System.Windows.Forms.CheckBox();\n            cb_HideFromView = new System.Windows.Forms.CheckBox();\n            cb_PinApp = new System.Windows.Forms.CheckBox();\n            cb_PinWindow = new System.Windows.Forms.CheckBox();\n            cb_FollowWindow = new System.Windows.Forms.CheckBox();\n            cbb_MoveToDesktop = new System.Windows.Forms.ComboBox();\n            cb_MoveToDesktop = new System.Windows.Forms.CheckBox();\n            btn_RuleSave = new System.Windows.Forms.Button();\n            statusBar = new System.Windows.Forms.StatusStrip();\n            toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel();\n            toolStripStatusLabel2 = new System.Windows.Forms.ToolStripStatusLabel();\n            gb_Info = new System.Windows.Forms.GroupBox();\n            lbUpdated = new System.Windows.Forms.Label();\n            lbCreated = new System.Windows.Forms.Label();\n            lb_Updated = new System.Windows.Forms.Label();\n            lb_Created = new System.Windows.Forms.Label();\n            gb_Basic.SuspendLayout();\n            gb_Rules.SuspendLayout();\n            gb_Actions.SuspendLayout();\n            statusBar.SuspendLayout();\n            gb_Info.SuspendLayout();\n            SuspendLayout();\n            // \n            // gb_Basic\n            // \n            resources.ApplyResources(gb_Basic, \"gb_Basic\");\n            gb_Basic.Controls.Add(cb_Enabled);\n            gb_Basic.Controls.Add(tb_Name);\n            gb_Basic.Controls.Add(lb_Name);\n            gb_Basic.Name = \"gb_Basic\";\n            gb_Basic.TabStop = false;\n            // \n            // cb_Enabled\n            // \n            resources.ApplyResources(cb_Enabled, \"cb_Enabled\");\n            cb_Enabled.Checked = true;\n            cb_Enabled.CheckState = System.Windows.Forms.CheckState.Checked;\n            cb_Enabled.Name = \"cb_Enabled\";\n            cb_Enabled.UseVisualStyleBackColor = true;\n            // \n            // tb_Name\n            // \n            resources.ApplyResources(tb_Name, \"tb_Name\");\n            tb_Name.BackColor = System.Drawing.SystemColors.Info;\n            tb_Name.Name = \"tb_Name\";\n            // \n            // lb_Name\n            // \n            resources.ApplyResources(lb_Name, \"lb_Name\");\n            lb_Name.Name = \"lb_Name\";\n            // \n            // gb_Rules\n            // \n            resources.ApplyResources(gb_Rules, \"gb_Rules\");\n            gb_Rules.Controls.Add(tb_CommandLine);\n            gb_Rules.Controls.Add(cbb_CommandLine);\n            gb_Rules.Controls.Add(cb_CommandLine);\n            gb_Rules.Controls.Add(cbb_WinInScreen);\n            gb_Rules.Controls.Add(cb_WinInScreen);\n            gb_Rules.Controls.Add(tb_WndClass);\n            gb_Rules.Controls.Add(cbb_WndClass);\n            gb_Rules.Controls.Add(cb_WndClass);\n            gb_Rules.Controls.Add(tb_ProcessPath);\n            gb_Rules.Controls.Add(cbb_ProcessPath);\n            gb_Rules.Controls.Add(cb_ProcessPath);\n            gb_Rules.Controls.Add(tb_ProcessName);\n            gb_Rules.Controls.Add(cbb_ProcessName);\n            gb_Rules.Controls.Add(cb_ProcessName);\n            gb_Rules.Controls.Add(tb_Title);\n            gb_Rules.Controls.Add(cbb_Title);\n            gb_Rules.Controls.Add(cb_Title);\n            gb_Rules.Name = \"gb_Rules\";\n            gb_Rules.TabStop = false;\n            // \n            // tb_CommandLine\n            // \n            resources.ApplyResources(tb_CommandLine, \"tb_CommandLine\");\n            tb_CommandLine.Name = \"tb_CommandLine\";\n            // \n            // cbb_CommandLine\n            // \n            resources.ApplyResources(cbb_CommandLine, \"cbb_CommandLine\");\n            cbb_CommandLine.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            cbb_CommandLine.FormattingEnabled = true;\n            cbb_CommandLine.Name = \"cbb_CommandLine\";\n            // \n            // cb_CommandLine\n            // \n            resources.ApplyResources(cb_CommandLine, \"cb_CommandLine\");\n            cb_CommandLine.Name = \"cb_CommandLine\";\n            cb_CommandLine.UseVisualStyleBackColor = true;\n            cb_CommandLine.CheckedChanged += checkBox_CheckedChanged;\n            // \n            // cbb_WinInScreen\n            // \n            resources.ApplyResources(cbb_WinInScreen, \"cbb_WinInScreen\");\n            cbb_WinInScreen.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            cbb_WinInScreen.FormattingEnabled = true;\n            cbb_WinInScreen.Name = \"cbb_WinInScreen\";\n            // \n            // cb_WinInScreen\n            // \n            resources.ApplyResources(cb_WinInScreen, \"cb_WinInScreen\");\n            cb_WinInScreen.Name = \"cb_WinInScreen\";\n            cb_WinInScreen.UseVisualStyleBackColor = true;\n            cb_WinInScreen.CheckedChanged += checkBox_CheckedChanged;\n            // \n            // tb_WndClass\n            // \n            resources.ApplyResources(tb_WndClass, \"tb_WndClass\");\n            tb_WndClass.Name = \"tb_WndClass\";\n            // \n            // cbb_WndClass\n            // \n            resources.ApplyResources(cbb_WndClass, \"cbb_WndClass\");\n            cbb_WndClass.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            cbb_WndClass.FormattingEnabled = true;\n            cbb_WndClass.Name = \"cbb_WndClass\";\n            // \n            // cb_WndClass\n            // \n            resources.ApplyResources(cb_WndClass, \"cb_WndClass\");\n            cb_WndClass.Name = \"cb_WndClass\";\n            cb_WndClass.UseVisualStyleBackColor = true;\n            cb_WndClass.CheckedChanged += checkBox_CheckedChanged;\n            // \n            // tb_ProcessPath\n            // \n            resources.ApplyResources(tb_ProcessPath, \"tb_ProcessPath\");\n            tb_ProcessPath.Name = \"tb_ProcessPath\";\n            // \n            // cbb_ProcessPath\n            // \n            resources.ApplyResources(cbb_ProcessPath, \"cbb_ProcessPath\");\n            cbb_ProcessPath.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            cbb_ProcessPath.FormattingEnabled = true;\n            cbb_ProcessPath.Name = \"cbb_ProcessPath\";\n            // \n            // cb_ProcessPath\n            // \n            resources.ApplyResources(cb_ProcessPath, \"cb_ProcessPath\");\n            cb_ProcessPath.Name = \"cb_ProcessPath\";\n            cb_ProcessPath.UseVisualStyleBackColor = true;\n            cb_ProcessPath.CheckedChanged += checkBox_CheckedChanged;\n            // \n            // tb_ProcessName\n            // \n            resources.ApplyResources(tb_ProcessName, \"tb_ProcessName\");\n            tb_ProcessName.Name = \"tb_ProcessName\";\n            // \n            // cbb_ProcessName\n            // \n            resources.ApplyResources(cbb_ProcessName, \"cbb_ProcessName\");\n            cbb_ProcessName.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            cbb_ProcessName.FormattingEnabled = true;\n            cbb_ProcessName.Name = \"cbb_ProcessName\";\n            // \n            // cb_ProcessName\n            // \n            resources.ApplyResources(cb_ProcessName, \"cb_ProcessName\");\n            cb_ProcessName.Name = \"cb_ProcessName\";\n            cb_ProcessName.UseVisualStyleBackColor = true;\n            cb_ProcessName.CheckedChanged += checkBox_CheckedChanged;\n            // \n            // tb_Title\n            // \n            resources.ApplyResources(tb_Title, \"tb_Title\");\n            tb_Title.Name = \"tb_Title\";\n            // \n            // cbb_Title\n            // \n            resources.ApplyResources(cbb_Title, \"cbb_Title\");\n            cbb_Title.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            cbb_Title.FormattingEnabled = true;\n            cbb_Title.Name = \"cbb_Title\";\n            // \n            // cb_Title\n            // \n            resources.ApplyResources(cb_Title, \"cb_Title\");\n            cb_Title.Name = \"cb_Title\";\n            cb_Title.UseVisualStyleBackColor = true;\n            cb_Title.CheckedChanged += checkBox_CheckedChanged;\n            // \n            // gb_Actions\n            // \n            resources.ApplyResources(gb_Actions, \"gb_Actions\");\n            gb_Actions.Controls.Add(cbb_MoveToScreen);\n            gb_Actions.Controls.Add(cb_MoveToScreen);\n            gb_Actions.Controls.Add(cb_HideFromView);\n            gb_Actions.Controls.Add(cb_PinApp);\n            gb_Actions.Controls.Add(cb_PinWindow);\n            gb_Actions.Controls.Add(cb_FollowWindow);\n            gb_Actions.Controls.Add(cbb_MoveToDesktop);\n            gb_Actions.Controls.Add(cb_MoveToDesktop);\n            gb_Actions.Name = \"gb_Actions\";\n            gb_Actions.TabStop = false;\n            // \n            // cbb_MoveToScreen\n            // \n            resources.ApplyResources(cbb_MoveToScreen, \"cbb_MoveToScreen\");\n            cbb_MoveToScreen.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            cbb_MoveToScreen.FormattingEnabled = true;\n            cbb_MoveToScreen.Name = \"cbb_MoveToScreen\";\n            // \n            // cb_MoveToScreen\n            // \n            resources.ApplyResources(cb_MoveToScreen, \"cb_MoveToScreen\");\n            cb_MoveToScreen.Name = \"cb_MoveToScreen\";\n            cb_MoveToScreen.UseVisualStyleBackColor = true;\n            cb_MoveToScreen.CheckedChanged += checkBox_CheckedChanged;\n            // \n            // cb_HideFromView\n            // \n            resources.ApplyResources(cb_HideFromView, \"cb_HideFromView\");\n            cb_HideFromView.Name = \"cb_HideFromView\";\n            cb_HideFromView.UseVisualStyleBackColor = true;\n            // \n            // cb_PinApp\n            // \n            resources.ApplyResources(cb_PinApp, \"cb_PinApp\");\n            cb_PinApp.Name = \"cb_PinApp\";\n            cb_PinApp.UseVisualStyleBackColor = true;\n            // \n            // cb_PinWindow\n            // \n            resources.ApplyResources(cb_PinWindow, \"cb_PinWindow\");\n            cb_PinWindow.Name = \"cb_PinWindow\";\n            cb_PinWindow.UseVisualStyleBackColor = true;\n            // \n            // cb_FollowWindow\n            // \n            resources.ApplyResources(cb_FollowWindow, \"cb_FollowWindow\");\n            cb_FollowWindow.Checked = true;\n            cb_FollowWindow.CheckState = System.Windows.Forms.CheckState.Checked;\n            cb_FollowWindow.Name = \"cb_FollowWindow\";\n            cb_FollowWindow.UseVisualStyleBackColor = true;\n            // \n            // cbb_MoveToDesktop\n            // \n            resources.ApplyResources(cbb_MoveToDesktop, \"cbb_MoveToDesktop\");\n            cbb_MoveToDesktop.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;\n            cbb_MoveToDesktop.FormattingEnabled = true;\n            cbb_MoveToDesktop.Name = \"cbb_MoveToDesktop\";\n            // \n            // cb_MoveToDesktop\n            // \n            resources.ApplyResources(cb_MoveToDesktop, \"cb_MoveToDesktop\");\n            cb_MoveToDesktop.Name = \"cb_MoveToDesktop\";\n            cb_MoveToDesktop.UseVisualStyleBackColor = true;\n            cb_MoveToDesktop.CheckedChanged += checkBox_CheckedChanged;\n            // \n            // btn_RuleSave\n            // \n            resources.ApplyResources(btn_RuleSave, \"btn_RuleSave\");\n            btn_RuleSave.Name = \"btn_RuleSave\";\n            btn_RuleSave.UseVisualStyleBackColor = true;\n            btn_RuleSave.Click += btn_RuleSave_Click;\n            // \n            // statusBar\n            // \n            resources.ApplyResources(statusBar, \"statusBar\");\n            statusBar.ImageScalingSize = new System.Drawing.Size(24, 24);\n            statusBar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { toolStripStatusLabel1, toolStripStatusLabel2 });\n            statusBar.Name = \"statusBar\";\n            statusBar.SizingGrip = false;\n            // \n            // toolStripStatusLabel1\n            // \n            resources.ApplyResources(toolStripStatusLabel1, \"toolStripStatusLabel1\");\n            toolStripStatusLabel1.Name = \"toolStripStatusLabel1\";\n            // \n            // toolStripStatusLabel2\n            // \n            resources.ApplyResources(toolStripStatusLabel2, \"toolStripStatusLabel2\");\n            toolStripStatusLabel2.Name = \"toolStripStatusLabel2\";\n            // \n            // gb_Info\n            // \n            resources.ApplyResources(gb_Info, \"gb_Info\");\n            gb_Info.Controls.Add(lbUpdated);\n            gb_Info.Controls.Add(lbCreated);\n            gb_Info.Controls.Add(lb_Updated);\n            gb_Info.Controls.Add(lb_Created);\n            gb_Info.Name = \"gb_Info\";\n            gb_Info.TabStop = false;\n            // \n            // lbUpdated\n            // \n            resources.ApplyResources(lbUpdated, \"lbUpdated\");\n            lbUpdated.Name = \"lbUpdated\";\n            // \n            // lbCreated\n            // \n            resources.ApplyResources(lbCreated, \"lbCreated\");\n            lbCreated.Name = \"lbCreated\";\n            // \n            // lb_Updated\n            // \n            resources.ApplyResources(lb_Updated, \"lb_Updated\");\n            lb_Updated.Name = \"lb_Updated\";\n            // \n            // lb_Created\n            // \n            resources.ApplyResources(lb_Created, \"lb_Created\");\n            lb_Created.Name = \"lb_Created\";\n            // \n            // RuleForm\n            // \n            resources.ApplyResources(this, \"$this\");\n            AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;\n            Controls.Add(gb_Info);\n            Controls.Add(statusBar);\n            Controls.Add(btn_RuleSave);\n            Controls.Add(gb_Actions);\n            Controls.Add(gb_Rules);\n            Controls.Add(gb_Basic);\n            FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;\n            MaximizeBox = false;\n            MinimizeBox = false;\n            Name = \"RuleForm\";\n            gb_Basic.ResumeLayout(false);\n            gb_Basic.PerformLayout();\n            gb_Rules.ResumeLayout(false);\n            gb_Rules.PerformLayout();\n            gb_Actions.ResumeLayout(false);\n            gb_Actions.PerformLayout();\n            statusBar.ResumeLayout(false);\n            statusBar.PerformLayout();\n            gb_Info.ResumeLayout(false);\n            gb_Info.PerformLayout();\n            ResumeLayout(false);\n            PerformLayout();\n        }\n\n        #endregion\n\n        private System.Windows.Forms.GroupBox gb_Basic;\n        private System.Windows.Forms.CheckBox cb_Enabled;\n        private System.Windows.Forms.TextBox tb_Name;\n        private System.Windows.Forms.Label lb_Name;\n        private System.Windows.Forms.GroupBox gb_Rules;\n        private System.Windows.Forms.ComboBox cbb_Title;\n        private System.Windows.Forms.CheckBox cb_Title;\n        private System.Windows.Forms.TextBox tb_Title;\n        private System.Windows.Forms.TextBox tb_WndClass;\n        private System.Windows.Forms.ComboBox cbb_WndClass;\n        private System.Windows.Forms.CheckBox cb_WndClass;\n        private System.Windows.Forms.TextBox tb_ProcessPath;\n        private System.Windows.Forms.ComboBox cbb_ProcessPath;\n        private System.Windows.Forms.CheckBox cb_ProcessPath;\n        private System.Windows.Forms.TextBox tb_ProcessName;\n        private System.Windows.Forms.ComboBox cbb_ProcessName;\n        private System.Windows.Forms.CheckBox cb_ProcessName;\n        private System.Windows.Forms.GroupBox gb_Actions;\n        private System.Windows.Forms.CheckBox cb_PinApp;\n        private System.Windows.Forms.CheckBox cb_PinWindow;\n        private System.Windows.Forms.CheckBox cb_FollowWindow;\n        private System.Windows.Forms.ComboBox cbb_MoveToDesktop;\n        private System.Windows.Forms.CheckBox cb_MoveToDesktop;\n        private System.Windows.Forms.Button btn_RuleSave;\n        private System.Windows.Forms.StatusStrip statusBar;\n        private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1;\n        private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel2;\n        private System.Windows.Forms.GroupBox gb_Info;\n        private System.Windows.Forms.Label lb_Updated;\n        private System.Windows.Forms.Label lb_Created;\n        private System.Windows.Forms.Label lbUpdated;\n        private System.Windows.Forms.Label lbCreated;\n        private System.Windows.Forms.CheckBox cb_HideFromView;\n        private System.Windows.Forms.ComboBox cbb_WinInScreen;\n        private System.Windows.Forms.CheckBox cb_WinInScreen;\n        private System.Windows.Forms.ComboBox cbb_MoveToScreen;\n        private System.Windows.Forms.CheckBox cb_MoveToScreen;\n        private System.Windows.Forms.TextBox tb_CommandLine;\n        private System.Windows.Forms.ComboBox cbb_CommandLine;\n        private System.Windows.Forms.CheckBox cb_CommandLine;\n    }\n}"
  },
  {
    "path": "WinForms/AppController/RuleForm.cs",
    "content": "﻿/* Copyright (C) 2022 Dylan Cheng (https://github.com/newlooper)\n\nThis file is part of VirtualSpace.\n\nVirtualSpace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\nVirtualSpace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with VirtualSpace. If not, see <https://www.gnu.org/licenses/>.\n*/\n\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\nusing System.Text.Json;\nusing System.Text.RegularExpressions;\nusing System.Windows.Forms;\nusing LinqExpressionBuilder;\nusing VirtualSpace.Config;\nusing VirtualSpace.Config.Events.Entity;\nusing VirtualSpace.Config.Events.Expression;\nusing VirtualSpace.Helpers;\nusing VirtualSpace.VirtualDesktop.Api;\nusing Process = System.Diagnostics.Process;\n\nnamespace VirtualSpace\n{\n    public partial class RuleForm : Form\n    {\n        private readonly Dictionary<string, Guid> _editIds = new();\n        private readonly int                      _editIndex;\n\n        public RuleForm()\n        {\n            InitializeComponent();\n            _editIndex = -1;\n        }\n\n        public RuleForm( int index )\n        {\n            InitializeComponent();\n            _editIndex = index;\n        }\n\n        public void Init()\n        {\n            InitOperators();\n            SetFormValues();\n        }\n\n        private void InitOperators()\n        {\n            OperatorList( cbb_Title );\n            OperatorList( cbb_ProcessName );\n            OperatorList( cbb_ProcessPath );\n            OperatorList( cbb_CommandLine );\n            OperatorList( cbb_WndClass );\n\n            //////////////////////////\n            // all virtual desktops\n            var count    = DesktopWrapper.Count;\n            var desktops = new List<object>();\n            for ( var i = 0; i < count; i++ )\n            {\n                desktops.Add( new {Value = i, Text = DesktopWrapper.DesktopNameFromIndex( i )} );\n            }\n\n            WinForms.SetComboBoxDataSource( cbb_MoveToDesktop, desktops );\n\n            //////////////////////////\n            // all screens\n            var screens    = new List<object>();\n            var allScreens = Screen.AllScreens;\n            for ( var i = 0; i < allScreens.Length; i++ )\n            {\n                screens.Add( new {Value = i, Text = $\"{allScreens[i].DeviceName}  ({allScreens[i].DeviceFriendlyName()})\"} );\n            }\n\n            WinForms.SetComboBoxDataSource( cbb_WinInScreen, screens );\n            WinForms.SetComboBoxDataSource( cbb_MoveToScreen, new List<object>( screens ) ); // avoid share a same list\n        }\n\n        private static void OperatorList( ComboBox cbb )\n        {\n            var items = new List<object>\n            {\n                new {Value = Keywords.Eq[0], Text = Agent.Langs.GetString( \"Rule.Op.Eq\" )},\n                new {Value = Keywords.StartsWith[0], Text = Agent.Langs.GetString( \"Rule.Op.Ssw\" )},\n                new {Value = Keywords.EndsWith[0], Text = Agent.Langs.GetString( \"Rule.Op.Esw\" )},\n                new {Value = Keywords.Contains[0], Text = Agent.Langs.GetString( \"Rule.Op.Sc\" )},\n                new {Value = Keywords.RegexIsMatch[0], Text = Agent.Langs.GetString( \"Rule.Op.Regex\" )}\n            };\n            WinForms.SetComboBoxDataSource( cbb, items );\n        }\n\n        private void SetFormValues()\n        {\n            if ( _editIndex < 0 ) return;\n\n            _editIds.Clear();\n\n            var ruleList = Conditions.FetchRules();\n            if ( ruleList.Count == 0 ) return;\n\n            cb_Enabled.Checked = ruleList[_editIndex].Enabled;\n            tb_Name.Text = ruleList[_editIndex].Name;\n            var root  = Conditions.ParseExpressionTemplate( ruleList[_editIndex].Expression );\n            var array = new List<ExpressionTemplate>();\n\n            if ( root.rules != null )\n            {\n                array.AddRange( root.rules );\n            }\n            else\n            {\n                array.Add( root );\n            }\n\n            foreach ( var rule in array )\n            {\n                var type      = rule.type;\n                var field     = rule.field;\n                var @operator = rule.@operator;\n                var valueNode = rule.value;\n                var id        = rule.id;\n\n                switch ( field )\n                {\n                    case RuleFields.Title:\n                        cb_Title.Checked = true;\n                        cbb_Title.SelectedValue = @operator;\n                        tb_Title.Text = valueNode.V;\n                        _editIds[RuleFields.Title] = id;\n                        break;\n                    case RuleFields.ProcessName:\n                        cb_ProcessName.Checked = true;\n                        cbb_ProcessName.SelectedValue = @operator;\n                        tb_ProcessName.Text = valueNode.V;\n                        _editIds[RuleFields.ProcessName] = id;\n                        break;\n                    case RuleFields.ProcessPath:\n                        cb_ProcessPath.Checked = true;\n                        cbb_ProcessPath.SelectedValue = @operator;\n                        tb_ProcessPath.Text = valueNode.V;\n                        _editIds[RuleFields.ProcessPath] = id;\n                        break;\n                    case RuleFields.CommandLine:\n                        cb_CommandLine.Checked = true;\n                        cbb_CommandLine.SelectedValue = @operator;\n                        tb_CommandLine.Text = valueNode.V;\n                        _editIds[RuleFields.CommandLine] = id;\n                        break;\n                    case RuleFields.WndClass:\n                        cb_WndClass.Checked = true;\n                        cbb_WndClass.SelectedValue = @operator;\n                        tb_WndClass.Text = valueNode.V;\n                        _editIds[RuleFields.WndClass] = id;\n                        break;\n                    case RuleFields.WinInScreen:\n                        cb_WinInScreen.Checked = true;\n                        cbb_WinInScreen.SelectedValue = int.Parse( valueNode.V );\n                        _editIds[RuleFields.WinInScreen] = id;\n                        break;\n                }\n\n                var action = ruleList[_editIndex].Action;\n\n                cb_PinWindow.Checked = action.PinWindow;\n                cb_PinApp.Checked = action.PinApp;\n                cb_HideFromView.Checked = action.HideFromView;\n\n                cb_MoveToDesktop.Checked = action.MoveToDesktop >= 0;\n                cbb_MoveToDesktop.SelectedValue = action.MoveToDesktop;\n                cb_FollowWindow.Checked = action.FollowWindow;\n\n                cb_MoveToScreen.Checked = action.MoveToScreen >= 0;\n                cbb_MoveToScreen.SelectedValue = action.MoveToScreen;\n            }\n\n            lbCreated.Text = $\"{ruleList[_editIndex].Created:yyyy-MM-dd HH:mm:ss}\";\n            lbUpdated.Text = $\"{ruleList[_editIndex].Updated:yyyy-MM-dd HH:mm:ss}\";\n        }\n\n        public void SetFormValuesByWindow( IntPtr handle )\n        {\n            tb_Name.Text = Agent.Langs.GetString( \"Rule.New\" );\n\n            cb_Title.Checked = true;\n            var sbTitle = new StringBuilder( Const.WindowTitleMaxLength );\n            User32.GetWindowText( handle, sbTitle, sbTitle.Capacity );\n            tb_Title.Text = sbTitle.ToString();\n\n            _ = User32.GetWindowThreadProcessId( handle, out var pId );\n            var process = Process.GetProcessById( pId );\n            cb_ProcessName.Checked = true;\n            tb_ProcessName.Text = process.ProcessName;\n\n            try\n            {\n                tb_ProcessPath.Text = process.MainModule?.FileName;\n            }\n            catch ( Exception ex )\n            {\n                cb_ProcessPath.Checked = false;\n                cb_ProcessPath.Enabled = false;\n                tb_ProcessPath.Text = ex.Message;\n            }\n\n            try\n            {\n                tb_CommandLine.Text = process.GetCommandLineArgs();\n            }\n            catch ( Exception ex )\n            {\n                cb_CommandLine.Checked = false;\n                cb_CommandLine.Enabled = false;\n                tb_CommandLine.Text = ex.Message;\n            }\n\n            var sbCName = new StringBuilder( Const.WindowClassMaxLength );\n            User32.GetClassName( handle, sbCName, sbCName.Capacity );\n            tb_WndClass.Text = sbCName.ToString();\n\n            var allScreens = Screen.AllScreens;\n            var screen     = Screen.FromHandle( handle );\n            for ( var i = 0; i < allScreens.Length; i++ )\n            {\n                if ( screen.DeviceName == allScreens[i].DeviceName )\n                {\n                    cbb_WinInScreen.SelectedValue = i;\n                    break;\n                }\n            }\n        }\n\n        private void btn_RuleSave_Click( object sender, EventArgs e )\n        {\n            toolStripStatusLabel1.Text = \"\";\n            toolStripStatusLabel2.Text = \"\";\n            if ( string.IsNullOrEmpty( tb_Name.Text ) )\n            {\n                toolStripStatusLabel1.Text = lb_Name.Text;\n                toolStripStatusLabel2.Text = Agent.Langs.GetString( \"Rule.NameRequired\" );\n                return;\n            }\n\n            if ( ( cb_Title.Checked ||\n                   cb_ProcessName.Checked ||\n                   cb_ProcessPath.Checked ||\n                   cb_CommandLine.Checked ||\n                   cb_WndClass.Checked ||\n                   cb_WinInScreen.Checked ) == false )\n            {\n                toolStripStatusLabel2.Text = Agent.Langs.GetString( \"Rule.AtLeastOne\" );\n                return;\n            }\n\n            var ruleList = Conditions.FetchRules();\n\n            var rule = new RuleTemplate();\n            var exp = new ExpressionTemplate\n            {\n                condition = Keywords.And,\n                rules = new List<ExpressionTemplate>()\n            };\n\n            if ( _editIndex > -1 )\n            {\n                rule.Id = ruleList[_editIndex].Id;\n                exp.id = Conditions.ParseExpressionTemplate( ruleList[_editIndex].Expression ).id;\n            }\n\n            try\n            {\n                BuildRule( cb_Title, cbb_Title, tb_Title, exp );\n                BuildRule( cb_ProcessName, cbb_ProcessName, tb_ProcessName, exp );\n                BuildRule( cb_ProcessPath, cbb_ProcessPath, tb_ProcessPath, exp );\n                BuildRule( cb_CommandLine, cbb_CommandLine, tb_CommandLine, exp );\n                BuildRule( cb_WndClass, cbb_WndClass, tb_WndClass, exp );\n                BuildRule( cb_WinInScreen, cbb_WinInScreen, null, exp );\n            }\n            catch ( Exception ex )\n            {\n                toolStripStatusLabel2.Text = ex.Message;\n                return;\n            }\n\n            var action = new Behavior();\n            if ( cb_MoveToDesktop.Checked )\n            {\n                action.MoveToDesktop = int.Parse( cbb_MoveToDesktop.SelectedValue.ToString() );\n            }\n\n            if ( cb_MoveToScreen.Checked )\n            {\n                action.MoveToScreen = int.Parse( cbb_MoveToScreen.SelectedValue.ToString() );\n            }\n\n            action.FollowWindow = cb_FollowWindow.Checked;\n            action.PinWindow = cb_PinWindow.Checked;\n            action.PinApp = cb_PinApp.Checked;\n            action.HideFromView = cb_HideFromView.Checked;\n\n            var time = DateTime.Now;\n            rule.Name = tb_Name.Text;\n            rule.Expression = JsonDocument.Parse( JsonSerializer.Serialize( exp, Conditions.GetJsonSerializerOptions() ) );\n            rule.Action = action;\n            rule.Enabled = cb_Enabled.Checked;\n            rule.Updated = time;\n\n            if ( _editIndex == -1 )\n            {\n                rule.Created = time;\n                ruleList.Add( rule );\n            }\n            else\n            {\n                rule.Created = ruleList[_editIndex].Created;\n                ruleList[_editIndex] = rule;\n            }\n\n            AppController.UpdateRuleListView( _editIndex, rule, ruleList );\n\n            Close();\n        }\n\n        private void BuildRule( CheckBox cb, ComboBox cbb, TextBox? tb, ExpressionTemplate exp )\n        {\n            if ( cb.Checked )\n            {\n                var V   = new Value();\n                var opt = cbb.SelectedValue.ToString();\n                if ( tb is null )\n                {\n                    opt = Keywords.Eq[0];\n                    V = new Value {V = cbb.SelectedValue.ToString()};\n                }\n                else\n                {\n                    if ( opt == Keywords.RegexIsMatch[0] && !IsValidRegex( tb.Text ) )\n                    {\n                        throw new Exception( \"Invalid Regex.\" );\n                    }\n\n                    V = new Value {V = tb.Text};\n                }\n\n                var name = cb.Name[3..]; // 偷懒的做法，依赖控件名称，因此控件更名时需要注意不要破坏对应关系\n\n                var rule = new ExpressionTemplate\n                {\n                    type = Keywords.String,\n                    field = cb.Name[3..],\n                    @operator = opt,\n                    value = V\n                };\n                if ( _editIds.ContainsKey( name ) )\n                {\n                    rule.id = _editIds[name];\n                }\n\n                exp.rules.Add( rule );\n            }\n        }\n\n        private static bool IsValidRegex( string pattern )\n        {\n            if ( string.IsNullOrWhiteSpace( pattern ) ) return false;\n\n            try\n            {\n                _ = Regex.Match( \"\", pattern );\n            }\n            catch ( ArgumentException )\n            {\n                return false;\n            }\n\n            return true;\n        }\n\n        private void checkBox_CheckedChanged( object sender, EventArgs e )\n        {\n            if ( cb_Title.Checked )\n            {\n                cbb_Title.Enabled = true;\n                tb_Title.Enabled = true;\n            }\n            else\n            {\n                cbb_Title.Enabled = false;\n                tb_Title.Enabled = false;\n            }\n\n            if ( cb_ProcessName.Checked )\n            {\n                cbb_ProcessName.Enabled = true;\n                tb_ProcessName.Enabled = true;\n            }\n            else\n            {\n                cbb_ProcessName.Enabled = false;\n                tb_ProcessName.Enabled = false;\n            }\n\n            if ( cb_ProcessPath.Checked )\n            {\n                cbb_ProcessPath.Enabled = true;\n                tb_ProcessPath.Enabled = true;\n            }\n            else\n            {\n                cbb_ProcessPath.Enabled = false;\n                tb_ProcessPath.Enabled = false;\n            }\n\n            if ( cb_CommandLine.Checked )\n            {\n                cbb_CommandLine.Enabled = true;\n                tb_CommandLine.Enabled = true;\n            }\n            else\n            {\n                cbb_CommandLine.Enabled = false;\n                tb_CommandLine.Enabled = false;\n            }\n\n            if ( cb_WndClass.Checked )\n            {\n                cbb_WndClass.Enabled = true;\n                tb_WndClass.Enabled = true;\n            }\n            else\n            {\n                cbb_WndClass.Enabled = false;\n                tb_WndClass.Enabled = false;\n            }\n\n            if ( cb_MoveToDesktop.Checked )\n            {\n                cbb_MoveToDesktop.Enabled = true;\n                cb_FollowWindow.Enabled = true;\n            }\n            else\n            {\n                cbb_MoveToDesktop.Enabled = false;\n                cb_FollowWindow.Enabled = false;\n            }\n\n            if ( cb_WinInScreen.Checked )\n            {\n                cbb_WinInScreen.Enabled = true;\n            }\n            else\n            {\n                cbb_WinInScreen.Enabled = false;\n            }\n\n            if ( cb_MoveToScreen.Checked )\n            {\n                cbb_MoveToScreen.Enabled = true;\n            }\n            else\n            {\n                cbb_MoveToScreen.Enabled = false;\n            }\n        }\n    }\n}"
  },
  {
    "path": "WinForms/AppController/RuleForm.resx",
    "content": "﻿<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"&gt;&gt;cb_ProcessPath.Name\" xml:space=\"preserve\">\n    <value>cb_ProcessPath</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_ProcessName.Parent\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <assembly alias=\"mscorlib\" name=\"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\" />\n  <data name=\"cb_PinWindow.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>7</value>\n  </data>\n  <data name=\"&gt;&gt;cb_PinApp.Name\" xml:space=\"preserve\">\n    <value>cb_PinApp</value>\n  </data>\n  <data name=\"&gt;&gt;lb_Updated.ZOrder\" xml:space=\"preserve\">\n    <value>2</value>\n  </data>\n  <data name=\"&gt;&gt;cb_ProcessPath.Parent\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <assembly alias=\"System.Windows.Forms\" name=\"System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\" />\n  <data name=\"btn_RuleSave.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;$this.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Form, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"gb_Actions.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <assembly alias=\"System.Drawing\" name=\"System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\" />\n  <data name=\"cbb_MoveToDesktop.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>493, 25</value>\n  </data>\n  <data name=\"cbb_MoveToScreen.Enabled\" type=\"System.Boolean, mscorlib\">\n    <value>False</value>\n  </data>\n  <data name=\"&gt;&gt;lbCreated.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"lbUpdated.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>0, 17</value>\n  </data>\n  <data name=\"&gt;&gt;lbCreated.Name\" xml:space=\"preserve\">\n    <value>lbCreated</value>\n  </data>\n  <data name=\"&gt;&gt;tb_Name.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;cb_FollowWindow.ZOrder\" xml:space=\"preserve\">\n    <value>5</value>\n  </data>\n  <data name=\"tb_ProcessName.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>252, 50</value>\n  </data>\n  <data name=\"&gt;&gt;cb_FollowWindow.Name\" xml:space=\"preserve\">\n    <value>cb_FollowWindow</value>\n  </data>\n  <data name=\"lb_Created.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;lb_Updated.Name\" xml:space=\"preserve\">\n    <value>lb_Updated</value>\n  </data>\n  <data name=\"&gt;&gt;cb_WinInScreen.ZOrder\" xml:space=\"preserve\">\n    <value>4</value>\n  </data>\n  <data name=\"cbb_ProcessPath.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"tb_ProcessPath.Enabled\" type=\"System.Boolean, mscorlib\">\n    <value>False</value>\n  </data>\n  <data name=\"cb_Enabled.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"cbb_MoveToScreen.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>613, 25</value>\n  </data>\n  <data name=\"tb_CommandLine.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>509, 23</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_MoveToScreen.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;lb_Created.Name\" xml:space=\"preserve\">\n    <value>lb_Created</value>\n  </data>\n  <data name=\"cbb_WinInScreen.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>16</value>\n  </data>\n  <assembly alias=\"System.Windows.Forms\" name=\"System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089\" />\n  <data name=\"$this.StartPosition\" type=\"System.Windows.Forms.FormStartPosition, System.Windows.Forms\">\n    <value>CenterScreen</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_WinInScreen.Parent\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_MoveToDesktop.Parent\" xml:space=\"preserve\">\n    <value>gb_Actions</value>\n  </data>\n  <data name=\"tb_Title.Enabled\" type=\"System.Boolean, mscorlib\">\n    <value>False</value>\n  </data>\n  <data name=\"cbb_Title.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>4</value>\n  </data>\n  <data name=\"lbUpdated.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 0, 2, 0</value>\n  </data>\n  <data name=\"&gt;&gt;tb_Title.Parent\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <data name=\"tb_WndClass.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>14</value>\n  </data>\n  <data name=\"&gt;&gt;cb_PinWindow.Name\" xml:space=\"preserve\">\n    <value>cb_PinWindow</value>\n  </data>\n  <data name=\"&gt;&gt;tb_ProcessPath.Name\" xml:space=\"preserve\">\n    <value>tb_ProcessPath</value>\n  </data>\n  <data name=\"&gt;&gt;cb_PinApp.ZOrder\" xml:space=\"preserve\">\n    <value>3</value>\n  </data>\n  <data name=\"lbCreated.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 0, 2, 0</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_Title.ZOrder\" xml:space=\"preserve\">\n    <value>15</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_WinInScreen.Name\" xml:space=\"preserve\">\n    <value>cbb_WinInScreen</value>\n  </data>\n  <data name=\"cb_WinInScreen.Text\" xml:space=\"preserve\">\n    <value>Window In Screen</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_ProcessPath.Name\" xml:space=\"preserve\">\n    <value>cbb_ProcessPath</value>\n  </data>\n  <data name=\"gb_Basic.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"cb_WndClass.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"tb_WndClass.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>509, 23</value>\n  </data>\n  <data name=\"gb_Info.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>454, 11</value>\n  </data>\n  <data name=\"lb_Updated.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"cb_PinApp.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>8</value>\n  </data>\n  <data name=\"&gt;&gt;cb_ProcessPath.ZOrder\" xml:space=\"preserve\">\n    <value>10</value>\n  </data>\n  <data name=\"cb_CommandLine.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>7, 106</value>\n  </data>\n  <data name=\"cb_MoveToDesktop.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;tb_ProcessName.ZOrder\" xml:space=\"preserve\">\n    <value>11</value>\n  </data>\n  <data name=\"&gt;&gt;lb_Name.Name\" xml:space=\"preserve\">\n    <value>lb_Name</value>\n  </data>\n  <data name=\"gb_Rules.Text\" xml:space=\"preserve\">\n    <value>Common Window Rule</value>\n  </data>\n  <data name=\"gb_Actions.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>2</value>\n  </data>\n  <data name=\"&gt;&gt;lb_Name.Parent\" xml:space=\"preserve\">\n    <value>gb_Basic</value>\n  </data>\n  <data name=\"&gt;&gt;lb_Updated.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"gb_Info.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>319, 86</value>\n  </data>\n  <data name=\"cb_Title.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>3</value>\n  </data>\n  <data name=\"cbb_WndClass.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>13</value>\n  </data>\n  <data name=\"cbb_CommandLine.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;lbUpdated.Name\" xml:space=\"preserve\">\n    <value>lbUpdated</value>\n  </data>\n  <data name=\"&gt;&gt;cb_WndClass.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cbb_ProcessName.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>102, 25</value>\n  </data>\n  <data name=\"cb_ProcessName.Text\" xml:space=\"preserve\">\n    <value>Process Name</value>\n  </data>\n  <data name=\"cb_WndClass.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"tb_Name.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>1</value>\n  </data>\n  <data name=\"&gt;&gt;cb_WinInScreen.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cbb_WinInScreen.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>148, 158</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_WndClass.Name\" xml:space=\"preserve\">\n    <value>cbb_WndClass</value>\n  </data>\n  <data name=\"tb_WndClass.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"cb_Title.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>102, 21</value>\n  </data>\n  <data name=\"&gt;&gt;cb_Enabled.Name\" xml:space=\"preserve\">\n    <value>cb_Enabled</value>\n  </data>\n  <data name=\"&gt;&gt;cb_PinApp.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cbb_MoveToScreen.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>11</value>\n  </data>\n  <data name=\"lb_Name.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>43, 17</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_WinInScreen.ZOrder\" xml:space=\"preserve\">\n    <value>3</value>\n  </data>\n  <data name=\"cbb_MoveToDesktop.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>5</value>\n  </data>\n  <data name=\"cb_PinApp.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>180, 21</value>\n  </data>\n  <data name=\"cbb_CommandLine.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>148, 104</value>\n  </data>\n  <data name=\"&gt;&gt;lbUpdated.Parent\" xml:space=\"preserve\">\n    <value>gb_Info</value>\n  </data>\n  <data name=\"cbb_CommandLine.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>18</value>\n  </data>\n  <data name=\"cb_HideFromView.Text\" xml:space=\"preserve\">\n    <value>Hide From View</value>\n  </data>\n  <data name=\"cb_MoveToScreen.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"tb_WndClass.Enabled\" type=\"System.Boolean, mscorlib\">\n    <value>False</value>\n  </data>\n  <data name=\"&gt;&gt;cb_WinInScreen.Name\" xml:space=\"preserve\">\n    <value>cb_WinInScreen</value>\n  </data>\n  <data name=\"&gt;&gt;cb_Title.Name\" xml:space=\"preserve\">\n    <value>cb_Title</value>\n  </data>\n  <data name=\"&gt;&gt;cb_ProcessName.Name\" xml:space=\"preserve\">\n    <value>cb_ProcessName</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Actions.Parent\" xml:space=\"preserve\">\n    <value>$this</value>\n  </data>\n  <data name=\"&gt;&gt;lb_Created.ZOrder\" xml:space=\"preserve\">\n    <value>3</value>\n  </data>\n  <data name=\"lbUpdated.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>87, 47</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_WinInScreen.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_Title.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"lb_Created.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 0, 2, 0</value>\n  </data>\n  <data name=\"&gt;&gt;btn_RuleSave.Name\" xml:space=\"preserve\">\n    <value>btn_RuleSave</value>\n  </data>\n  <data name=\"gb_Actions.Text\" xml:space=\"preserve\">\n    <value>Window Actions</value>\n  </data>\n  <data name=\"$this.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"lbUpdated.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>3</value>\n  </data>\n  <data name=\"&gt;&gt;tb_CommandLine.Name\" xml:space=\"preserve\">\n    <value>tb_CommandLine</value>\n  </data>\n  <data name=\"&gt;&gt;cb_MoveToDesktop.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Basic.Parent\" xml:space=\"preserve\">\n    <value>$this</value>\n  </data>\n  <data name=\"gb_Info.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;tb_ProcessName.Parent\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <data name=\"lb_Name.Text\" xml:space=\"preserve\">\n    <value>Name</value>\n  </data>\n  <data name=\"cb_WinInScreen.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_ProcessPath.Parent\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <data name=\"cbb_WndClass.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>148, 131</value>\n  </data>\n  <data name=\"tb_ProcessPath.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>252, 78</value>\n  </data>\n  <data name=\"&gt;&gt;cb_HideFromView.Name\" xml:space=\"preserve\">\n    <value>cb_HideFromView</value>\n  </data>\n  <data name=\"&gt;&gt;statusBar.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"cb_ProcessPath.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"cbb_CommandLine.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>102, 25</value>\n  </data>\n  <data name=\"cb_FollowWindow.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>6</value>\n  </data>\n  <data name=\"cb_PinWindow.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"lb_Created.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>54, 17</value>\n  </data>\n  <data name=\"&gt;&gt;cb_PinApp.Parent\" xml:space=\"preserve\">\n    <value>gb_Actions</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_ProcessPath.ZOrder\" xml:space=\"preserve\">\n    <value>9</value>\n  </data>\n  <data name=\"$this.ClientSize\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>784, 561</value>\n  </data>\n  <data name=\"cb_MoveToDesktop.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>132, 21</value>\n  </data>\n  <data name=\"&gt;&gt;tb_Title.ZOrder\" xml:space=\"preserve\">\n    <value>14</value>\n  </data>\n  <data name=\"cbb_WndClass.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>102, 25</value>\n  </data>\n  <data name=\"cb_WinInScreen.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>15</value>\n  </data>\n  <data name=\"cb_MoveToScreen.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>10</value>\n  </data>\n  <data name=\"lb_Created.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"&gt;&gt;cb_PinWindow.ZOrder\" xml:space=\"preserve\">\n    <value>4</value>\n  </data>\n  <data name=\"&gt;&gt;statusBar.Parent\" xml:space=\"preserve\">\n    <value>$this</value>\n  </data>\n  <data name=\"cbb_Title.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>148, 23</value>\n  </data>\n  <data name=\"&gt;&gt;tb_WndClass.Name\" xml:space=\"preserve\">\n    <value>tb_WndClass</value>\n  </data>\n  <data name=\"&gt;&gt;cb_WinInScreen.Parent\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <data name=\"cb_PinApp.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"cb_ProcessName.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>111, 21</value>\n  </data>\n  <data name=\"&gt;&gt;btn_RuleSave.ZOrder\" xml:space=\"preserve\">\n    <value>2</value>\n  </data>\n  <data name=\"cb_WndClass.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"&gt;&gt;cb_WndClass.Parent\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <data name=\"gb_Info.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;cb_MoveToDesktop.Parent\" xml:space=\"preserve\">\n    <value>gb_Actions</value>\n  </data>\n  <data name=\"&gt;&gt;lb_Created.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_MoveToScreen.Text\" xml:space=\"preserve\">\n    <value>Move To Screen</value>\n  </data>\n  <data name=\"cb_HideFromView.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>9</value>\n  </data>\n  <data name=\"&gt;&gt;cb_ProcessPath.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;lb_Name.ZOrder\" xml:space=\"preserve\">\n    <value>2</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Basic.Name\" xml:space=\"preserve\">\n    <value>gb_Basic</value>\n  </data>\n  <data name=\"cb_CommandLine.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"cb_HideFromView.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>119, 21</value>\n  </data>\n  <data name=\"cb_ProcessName.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Rules.Name\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <data name=\"btn_RuleSave.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>665, 507</value>\n  </data>\n  <data name=\"lb_Updated.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>4, 47</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Info.Parent\" xml:space=\"preserve\">\n    <value>$this</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_CommandLine.Parent\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <data name=\"&gt;&gt;cb_HideFromView.ZOrder\" xml:space=\"preserve\">\n    <value>2</value>\n  </data>\n  <data name=\"&gt;&gt;cb_MoveToDesktop.Name\" xml:space=\"preserve\">\n    <value>cb_MoveToDesktop</value>\n  </data>\n  <data name=\"&gt;&gt;tb_ProcessName.Name\" xml:space=\"preserve\">\n    <value>tb_ProcessName</value>\n  </data>\n  <data name=\"cbb_ProcessPath.Enabled\" type=\"System.Boolean, mscorlib\">\n    <value>False</value>\n  </data>\n  <data name=\"&gt;&gt;toolStripStatusLabel1.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;toolStripStatusLabel1.Name\" xml:space=\"preserve\">\n    <value>toolStripStatusLabel1</value>\n  </data>\n  <data name=\"cbb_WndClass.Enabled\" type=\"System.Boolean, mscorlib\">\n    <value>False</value>\n  </data>\n  <data name=\"&gt;&gt;tb_CommandLine.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cbb_MoveToDesktop.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"$this.AutoScaleDimensions\" type=\"System.Drawing.SizeF, System.Drawing\">\n    <value>7, 17</value>\n  </data>\n  <data name=\"&gt;&gt;tb_CommandLine.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_WndClass.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_MoveToScreen.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>7, 132</value>\n  </data>\n  <data name=\"cb_MoveToScreen.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"cb_PinWindow.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>7, 51</value>\n  </data>\n  <data name=\"&gt;&gt;cb_WndClass.Name\" xml:space=\"preserve\">\n    <value>cb_WndClass</value>\n  </data>\n  <data name=\"&gt;&gt;cb_PinWindow.Parent\" xml:space=\"preserve\">\n    <value>gb_Actions</value>\n  </data>\n  <data name=\"&gt;&gt;statusBar.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.StatusStrip, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"lbCreated.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"cbb_MoveToDesktop.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>148, 23</value>\n  </data>\n  <data name=\"tb_Title.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"statusBar.Text\" xml:space=\"preserve\">\n    <value>statusStrip1</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_CommandLine.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"&gt;&gt;toolStripStatusLabel2.Name\" xml:space=\"preserve\">\n    <value>toolStripStatusLabel2</value>\n  </data>\n  <data name=\"lb_Updated.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Rules.ZOrder\" xml:space=\"preserve\">\n    <value>4</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_MoveToDesktop.Name\" xml:space=\"preserve\">\n    <value>cbb_MoveToDesktop</value>\n  </data>\n  <data name=\"cb_ProcessPath.Text\" xml:space=\"preserve\">\n    <value>Process Path</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Rules.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;btn_RuleSave.Parent\" xml:space=\"preserve\">\n    <value>$this</value>\n  </data>\n  <data name=\"cb_ProcessPath.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>9</value>\n  </data>\n  <data name=\"lbCreated.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>87, 23</value>\n  </data>\n  <data name=\"&gt;&gt;tb_Title.Name\" xml:space=\"preserve\">\n    <value>tb_Title</value>\n  </data>\n  <data name=\"&gt;&gt;toolStripStatusLabel2.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;cb_PinWindow.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"gb_Basic.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>442, 89</value>\n  </data>\n  <data name=\"&gt;&gt;cb_MoveToScreen.Name\" xml:space=\"preserve\">\n    <value>cb_MoveToScreen</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_MoveToScreen.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"cb_CommandLine.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>17</value>\n  </data>\n  <data name=\"tb_Title.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>5</value>\n  </data>\n  <data name=\"&gt;&gt;cb_HideFromView.Parent\" xml:space=\"preserve\">\n    <value>gb_Actions</value>\n  </data>\n  <data name=\"cb_Enabled.Text\" xml:space=\"preserve\">\n    <value>Enabled</value>\n  </data>\n  <data name=\"statusBar.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>1, 0, 9, 0</value>\n  </data>\n  <data name=\"gb_Rules.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;cb_ProcessName.Parent\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <data name=\"tb_CommandLine.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>252, 105</value>\n  </data>\n  <data name=\"lbCreated.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>2</value>\n  </data>\n  <data name=\"gb_Rules.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"tb_Name.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>50, 21</value>\n  </data>\n  <data name=\"cbb_ProcessName.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>7</value>\n  </data>\n  <data name=\"btn_RuleSave.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>108, 24</value>\n  </data>\n  <data name=\"tb_Title.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>509, 23</value>\n  </data>\n  <data name=\"&gt;&gt;cb_ProcessName.ZOrder\" xml:space=\"preserve\">\n    <value>13</value>\n  </data>\n  <data name=\"cbb_WinInScreen.Enabled\" type=\"System.Boolean, mscorlib\">\n    <value>False</value>\n  </data>\n  <data name=\"cb_WinInScreen.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>7, 160</value>\n  </data>\n  <data name=\"gb_Rules.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>8, 101</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_Title.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_MoveToDesktop.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>7, 24</value>\n  </data>\n  <data name=\"tb_ProcessName.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>8</value>\n  </data>\n  <data name=\"cbb_WndClass.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Basic.ZOrder\" xml:space=\"preserve\">\n    <value>5</value>\n  </data>\n  <data name=\"cb_ProcessName.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>7, 51</value>\n  </data>\n  <data name=\"&gt;&gt;cb_MoveToDesktop.ZOrder\" xml:space=\"preserve\">\n    <value>7</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_Title.Name\" xml:space=\"preserve\">\n    <value>cbb_Title</value>\n  </data>\n  <data name=\"cb_WinInScreen.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>132, 21</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_ProcessName.Name\" xml:space=\"preserve\">\n    <value>cbb_ProcessName</value>\n  </data>\n  <data name=\"cbb_ProcessPath.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>102, 25</value>\n  </data>\n  <data name=\"&gt;&gt;cb_WndClass.ZOrder\" xml:space=\"preserve\">\n    <value>7</value>\n  </data>\n  <data name=\"cb_WndClass.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>7, 133</value>\n  </data>\n  <data name=\"&gt;&gt;tb_ProcessPath.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;cb_MoveToScreen.Parent\" xml:space=\"preserve\">\n    <value>gb_Actions</value>\n  </data>\n  <data name=\"&gt;&gt;lbUpdated.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;cb_CommandLine.Name\" xml:space=\"preserve\">\n    <value>cb_CommandLine</value>\n  </data>\n  <data name=\"cb_FollowWindow.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"&gt;&gt;lb_Name.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"lb_Name.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"&gt;&gt;cb_CommandLine.Parent\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <data name=\"statusBar.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>784, 22</value>\n  </data>\n  <data name=\"cb_WndClass.Text\" xml:space=\"preserve\">\n    <value>Window Class</value>\n  </data>\n  <data name=\"&gt;&gt;tb_Name.Parent\" xml:space=\"preserve\">\n    <value>gb_Basic</value>\n  </data>\n  <data name=\"&gt;&gt;statusBar.Name\" xml:space=\"preserve\">\n    <value>statusBar</value>\n  </data>\n  <data name=\"&gt;&gt;cb_Title.ZOrder\" xml:space=\"preserve\">\n    <value>16</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Actions.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"gb_Basic.Text\" xml:space=\"preserve\">\n    <value>Basic</value>\n  </data>\n  <data name=\"cb_WinInScreen.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"&gt;&gt;cb_Enabled.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"cb_FollowWindow.Enabled\" type=\"System.Boolean, mscorlib\">\n    <value>False</value>\n  </data>\n  <data name=\"&gt;&gt;tb_Title.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;cb_MoveToScreen.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"&gt;&gt;cb_FollowWindow.Parent\" xml:space=\"preserve\">\n    <value>gb_Actions</value>\n  </data>\n  <data name=\"&gt;&gt;cb_CommandLine.ZOrder\" xml:space=\"preserve\">\n    <value>2</value>\n  </data>\n  <data name=\"tb_CommandLine.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;tb_WndClass.Parent\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <data name=\"lbUpdated.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"cbb_Title.Enabled\" type=\"System.Boolean, mscorlib\">\n    <value>False</value>\n  </data>\n  <data name=\"cb_Title.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"gb_Actions.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>765, 173</value>\n  </data>\n  <data name=\"cbb_CommandLine.Enabled\" type=\"System.Boolean, mscorlib\">\n    <value>False</value>\n  </data>\n  <data name=\"toolStripStatusLabel1.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>0, 17</value>\n  </data>\n  <data name=\"&gt;&gt;cb_HideFromView.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_Title.Parent\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <data name=\"&gt;&gt;tb_ProcessPath.Parent\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <data name=\"cb_HideFromView.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"&gt;&gt;cb_Title.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"lb_Name.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 0, 2, 0</value>\n  </data>\n  <data name=\"&gt;&gt;cb_ProcessName.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Actions.Name\" xml:space=\"preserve\">\n    <value>gb_Actions</value>\n  </data>\n  <data name=\"&gt;&gt;cb_Title.Parent\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Info.Name\" xml:space=\"preserve\">\n    <value>gb_Info</value>\n  </data>\n  <data name=\"gb_Info.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>5</value>\n  </data>\n  <data name=\"cb_CommandLine.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_WndClass.Parent\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <data name=\"cb_MoveToScreen.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>122, 21</value>\n  </data>\n  <data name=\"cb_PinApp.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>7, 78</value>\n  </data>\n  <data name=\"cb_ProcessPath.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>7, 79</value>\n  </data>\n  <data name=\"cb_Enabled.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"&gt;&gt;tb_Name.Name\" xml:space=\"preserve\">\n    <value>tb_Name</value>\n  </data>\n  <data name=\"cb_Title.Text\" xml:space=\"preserve\">\n    <value>Window Title</value>\n  </data>\n  <data name=\"&gt;&gt;cb_MoveToScreen.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"lb_Created.Text\" xml:space=\"preserve\">\n    <value>Created</value>\n  </data>\n  <data name=\"cbb_ProcessName.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"cbb_Title.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_MoveToScreen.Name\" xml:space=\"preserve\">\n    <value>cbb_MoveToScreen</value>\n  </data>\n  <data name=\"lb_Created.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>4, 23</value>\n  </data>\n  <data name=\"tb_ProcessName.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"cb_ProcessName.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"&gt;&gt;cb_Enabled.Parent\" xml:space=\"preserve\">\n    <value>gb_Basic</value>\n  </data>\n  <data name=\"cbb_ProcessPath.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>10</value>\n  </data>\n  <data name=\"cb_PinWindow.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Actions.ZOrder\" xml:space=\"preserve\">\n    <value>3</value>\n  </data>\n  <data name=\"tb_CommandLine.Enabled\" type=\"System.Boolean, mscorlib\">\n    <value>False</value>\n  </data>\n  <data name=\"&gt;&gt;tb_WndClass.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"statusBar.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>0, 539</value>\n  </data>\n  <data name=\"cbb_MoveToDesktop.Enabled\" type=\"System.Boolean, mscorlib\">\n    <value>False</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_MoveToScreen.Parent\" xml:space=\"preserve\">\n    <value>gb_Actions</value>\n  </data>\n  <data name=\"cb_ProcessName.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"cb_CommandLine.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"cb_ProcessName.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>6</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_CommandLine.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_Title.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"&gt;&gt;lbCreated.Parent\" xml:space=\"preserve\">\n    <value>gb_Info</value>\n  </data>\n  <data name=\"lbCreated.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>0, 17</value>\n  </data>\n  <data name=\"tb_Name.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>380, 23</value>\n  </data>\n  <data name=\"gb_Basic.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>0</value>\n  </data>\n  <data name=\"cbb_MoveToScreen.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"cb_FollowWindow.Text\" xml:space=\"preserve\">\n    <value>Follow Window</value>\n  </data>\n  <data name=\"cbb_WinInScreen.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>613, 25</value>\n  </data>\n  <data name=\"btn_RuleSave.Text\" xml:space=\"preserve\">\n    <value>Save</value>\n  </data>\n  <data name=\"cb_ProcessPath.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"tb_ProcessPath.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>11</value>\n  </data>\n  <data name=\"tb_Title.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>252, 23</value>\n  </data>\n  <data name=\"cb_MoveToDesktop.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>4</value>\n  </data>\n  <data name=\"&gt;&gt;tb_WndClass.ZOrder\" xml:space=\"preserve\">\n    <value>5</value>\n  </data>\n  <data name=\"cb_FollowWindow.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>646, 25</value>\n  </data>\n  <data name=\"cb_FollowWindow.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>115, 21</value>\n  </data>\n  <data name=\"&gt;&gt;cb_FollowWindow.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_Title.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>7, 24</value>\n  </data>\n  <data name=\"cb_FollowWindow.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"cb_ProcessPath.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>101, 21</value>\n  </data>\n  <data name=\"&gt;&gt;lb_Created.Parent\" xml:space=\"preserve\">\n    <value>gb_Info</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_MoveToDesktop.ZOrder\" xml:space=\"preserve\">\n    <value>6</value>\n  </data>\n  <data name=\"cb_PinWindow.Text\" xml:space=\"preserve\">\n    <value>Pin Window</value>\n  </data>\n  <data name=\"cb_WndClass.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>108, 21</value>\n  </data>\n  <data name=\"gb_Actions.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"cb_WndClass.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>12</value>\n  </data>\n  <data name=\"tb_ProcessName.Enabled\" type=\"System.Boolean, mscorlib\">\n    <value>False</value>\n  </data>\n  <data name=\"&gt;&gt;tb_Name.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"cb_PinWindow.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Rules.Parent\" xml:space=\"preserve\">\n    <value>$this</value>\n  </data>\n  <data name=\"cbb_ProcessName.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>148, 50</value>\n  </data>\n  <data name=\"lb_Name.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>0</value>\n  </data>\n  <data name=\"&gt;&gt;lb_Updated.Parent\" xml:space=\"preserve\">\n    <value>gb_Info</value>\n  </data>\n  <data name=\"cbb_ProcessPath.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>148, 77</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_ProcessName.ZOrder\" xml:space=\"preserve\">\n    <value>12</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Info.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_CommandLine.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>114, 21</value>\n  </data>\n  <data name=\"toolStripStatusLabel1.Font\" type=\"System.Drawing.Font, System.Drawing\">\n    <value>Microsoft YaHei UI, 9pt, style=Bold</value>\n  </data>\n  <data name=\"cb_MoveToDesktop.Text\" xml:space=\"preserve\">\n    <value>Move To Desktop</value>\n  </data>\n  <data name=\"btn_RuleSave.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>3</value>\n  </data>\n  <data name=\"cb_WinInScreen.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"tb_ProcessPath.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>509, 23</value>\n  </data>\n  <data name=\"cb_MoveToDesktop.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Basic.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;gb_Info.ZOrder\" xml:space=\"preserve\">\n    <value>0</value>\n  </data>\n  <data name=\"gb_Basic.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>8, 8</value>\n  </data>\n  <data name=\"&gt;&gt;tb_CommandLine.Parent\" xml:space=\"preserve\">\n    <value>gb_Rules</value>\n  </data>\n  <data name=\"tb_ProcessName.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>509, 23</value>\n  </data>\n  <data name=\"lb_Updated.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>59, 17</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_CommandLine.Name\" xml:space=\"preserve\">\n    <value>cbb_CommandLine</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_MoveToDesktop.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_ProcessPath.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cb_Enabled.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>7, 52</value>\n  </data>\n  <data name=\"gb_Rules.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>765, 200</value>\n  </data>\n  <data name=\"&gt;&gt;lbUpdated.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cbb_WinInScreen.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"gb_Info.Text\" xml:space=\"preserve\">\n    <value>Info</value>\n  </data>\n  <data name=\"cb_FollowWindow.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"lbCreated.AutoSize\" type=\"System.Boolean, mscorlib\">\n    <value>True</value>\n  </data>\n  <data name=\"lbUpdated.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"cb_PinWindow.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>95, 21</value>\n  </data>\n  <data name=\"&gt;&gt;btn_RuleSave.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"tb_WndClass.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>252, 132</value>\n  </data>\n  <data name=\"&gt;&gt;cb_CommandLine.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;cb_Enabled.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"&gt;&gt;tb_ProcessName.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cbb_MoveToScreen.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>148, 130</value>\n  </data>\n  <data name=\"cb_Enabled.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>2</value>\n  </data>\n  <data name=\"lb_Updated.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 0, 2, 0</value>\n  </data>\n  <data name=\"cb_CommandLine.Text\" xml:space=\"preserve\">\n    <value>Command Line</value>\n  </data>\n  <data name=\"cb_Enabled.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>74, 21</value>\n  </data>\n  <data name=\"cb_PinApp.Text\" xml:space=\"preserve\">\n    <value>Pin Application of Window</value>\n  </data>\n  <data name=\"lb_Updated.Text\" xml:space=\"preserve\">\n    <value>Updated</value>\n  </data>\n  <data name=\"tb_ProcessPath.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"toolStripStatusLabel2.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>0, 17</value>\n  </data>\n  <data name=\"gb_Basic.Padding\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"cb_HideFromView.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>7, 105</value>\n  </data>\n  <data name=\"cbb_Title.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>102, 25</value>\n  </data>\n  <data name=\"tb_CommandLine.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>19</value>\n  </data>\n  <data name=\"gb_Actions.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>8, 306</value>\n  </data>\n  <data name=\"&gt;&gt;$this.Name\" xml:space=\"preserve\">\n    <value>RuleForm</value>\n  </data>\n  <data name=\"cb_ProcessPath.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"statusBar.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>4</value>\n  </data>\n  <data name=\"cb_PinApp.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"gb_Rules.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>1</value>\n  </data>\n  <data name=\"lb_Updated.TabIndex\" type=\"System.Int32, mscorlib\">\n    <value>1</value>\n  </data>\n  <data name=\"cb_HideFromView.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"cb_MoveToScreen.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"cb_PinApp.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"lb_Name.Location\" type=\"System.Drawing.Point, System.Drawing\">\n    <value>4, 23</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_WndClass.ZOrder\" xml:space=\"preserve\">\n    <value>6</value>\n  </data>\n  <data name=\"cb_MoveToDesktop.ImeMode\" type=\"System.Windows.Forms.ImeMode, System.Windows.Forms\">\n    <value>NoControl</value>\n  </data>\n  <data name=\"&gt;&gt;tb_ProcessPath.ZOrder\" xml:space=\"preserve\">\n    <value>8</value>\n  </data>\n  <data name=\"$this.Text\" xml:space=\"preserve\">\n    <value>Rule Definition</value>\n  </data>\n  <data name=\"tb_Name.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <data name=\"&gt;&gt;lbCreated.ZOrder\" xml:space=\"preserve\">\n    <value>1</value>\n  </data>\n  <data name=\"&gt;&gt;cbb_ProcessName.Type\" xml:space=\"preserve\">\n    <value>System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </data>\n  <data name=\"cbb_ProcessName.Enabled\" type=\"System.Boolean, mscorlib\">\n    <value>False</value>\n  </data>\n  <data name=\"cb_HideFromView.Margin\" type=\"System.Windows.Forms.Padding, System.Windows.Forms\">\n    <value>2, 2, 2, 2</value>\n  </data>\n  <metadata name=\"statusBar.TrayLocation\" type=\"System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n    <value>17, 17</value>\n  </metadata>\n  <metadata name=\"$this.Language\" type=\"System.Globalization.CultureInfo, System.Private.CoreLib, Culture=neutral, PublicKeyToken=7cec85d7bea7798e\">\n    <value>zh-Hans</value>\n  </metadata>\n  <metadata name=\"$this.Localizable\" type=\"System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>True</value>\n  </metadata>\n</root>"
  },
  {
    "path": "WinForms/AppController/RuleForm.zh-Hans.resx",
    "content": "﻿<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <assembly alias=\"System.Drawing\" name=\"System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\" />\n  <data name=\"cb_Enabled.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>51, 21</value>\n  </data>\n  <data name=\"cb_Enabled.Text\" xml:space=\"preserve\">\n    <value>启用</value>\n  </data>\n  <data name=\"lb_Name.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>32, 17</value>\n  </data>\n  <data name=\"lb_Name.Text\" xml:space=\"preserve\">\n    <value>名称</value>\n  </data>\n  <data name=\"gb_Basic.Text\" xml:space=\"preserve\">\n    <value>基本</value>\n  </data>\n  <data name=\"cb_CommandLine.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>63, 21</value>\n  </data>\n  <data name=\"cb_CommandLine.Text\" xml:space=\"preserve\">\n    <value>命令行</value>\n  </data>\n  <data name=\"cb_WinInScreen.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>99, 21</value>\n  </data>\n  <data name=\"cb_WinInScreen.Text\" xml:space=\"preserve\">\n    <value>窗口位于屏幕</value>\n  </data>\n  <data name=\"cb_WndClass.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>75, 21</value>\n  </data>\n  <data name=\"cb_WndClass.Text\" xml:space=\"preserve\">\n    <value>窗口类名</value>\n  </data>\n  <data name=\"cb_ProcessPath.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>75, 21</value>\n  </data>\n  <data name=\"cb_ProcessPath.Text\" xml:space=\"preserve\">\n    <value>进程路径</value>\n  </data>\n  <data name=\"cb_ProcessName.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>75, 21</value>\n  </data>\n  <data name=\"cb_ProcessName.Text\" xml:space=\"preserve\">\n    <value>进程名称</value>\n  </data>\n  <data name=\"cb_Title.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>75, 21</value>\n  </data>\n  <data name=\"cb_Title.Text\" xml:space=\"preserve\">\n    <value>窗口标题</value>\n  </data>\n  <data name=\"gb_Rules.Text\" xml:space=\"preserve\">\n    <value>公共窗口规则</value>\n  </data>\n  <data name=\"cb_MoveToScreen.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>87, 21</value>\n  </data>\n  <data name=\"cb_MoveToScreen.Text\" xml:space=\"preserve\">\n    <value>移动到屏幕</value>\n  </data>\n  <data name=\"cb_HideFromView.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>99, 21</value>\n  </data>\n  <data name=\"cb_HideFromView.Text\" xml:space=\"preserve\">\n    <value>从视图中隐藏</value>\n  </data>\n  <data name=\"cb_PinApp.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>195, 21</value>\n  </data>\n  <data name=\"cb_PinApp.Text\" xml:space=\"preserve\">\n    <value>在所有桌面上显示此应用的窗口</value>\n  </data>\n  <data name=\"cb_PinWindow.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>159, 21</value>\n  </data>\n  <data name=\"cb_PinWindow.Text\" xml:space=\"preserve\">\n    <value>在所有桌面上显示此窗口</value>\n  </data>\n  <data name=\"cb_FollowWindow.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>111, 21</value>\n  </data>\n  <data name=\"cb_FollowWindow.Text\" xml:space=\"preserve\">\n    <value>跟随窗口到桌面</value>\n  </data>\n  <data name=\"cb_MoveToDesktop.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>87, 21</value>\n  </data>\n  <data name=\"cb_MoveToDesktop.Text\" xml:space=\"preserve\">\n    <value>移动到桌面</value>\n  </data>\n  <data name=\"gb_Actions.Text\" xml:space=\"preserve\">\n    <value>窗口动作</value>\n  </data>\n  <data name=\"btn_RuleSave.Text\" xml:space=\"preserve\">\n    <value>保存</value>\n  </data>\n  <data name=\"lb_Updated.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>56, 17</value>\n  </data>\n  <data name=\"lb_Updated.Text\" xml:space=\"preserve\">\n    <value>更新时间</value>\n  </data>\n  <data name=\"lb_Created.Size\" type=\"System.Drawing.Size, System.Drawing\">\n    <value>56, 17</value>\n  </data>\n  <data name=\"lb_Created.Text\" xml:space=\"preserve\">\n    <value>创建时间</value>\n  </data>\n  <data name=\"gb_Info.Text\" xml:space=\"preserve\">\n    <value>信息</value>\n  </data>\n  <data name=\"$this.Text\" xml:space=\"preserve\">\n    <value>规则定义</value>\n  </data>\n</root>"
  }
]