Compare commits

...

61 Commits

Author SHA1 Message Date
Mike Griese d675fd824a figure this out 2021-11-16 06:35:31 -06:00
Mike Griese b421ee6ca0 Merge remote-tracking branch 'origin/main' into dev/migrie/oop/ragnarok 2021-11-16 06:22:35 -06:00
Mike Griese a1bfa332f3 this was a nit 2021-11-11 16:33:05 -06:00
Mike Griese 8313987490 tests are hard 2021-11-11 16:32:26 -06:00
Mike Griese efdc0909e8 fix the tests 2021-11-11 12:52:08 -06:00
Mike Griese 7bb8975953 more todos 2021-11-11 11:40:15 -06:00
Mike Griese 8532dd692e fix conflicts with #11625 2021-11-11 11:38:50 -06:00
Mike Griese a338ca168c Merge remote-tracking branch 'origin/main' into dev/migrie/oop/ragnarok 2021-11-11 11:08:54 -06:00
Mike Griese 5adb327703 rename this one too 2021-11-11 10:34:25 -06:00
Mike Griese 1a7649ce21 turns out this _was_ overkill 2021-11-11 10:24:09 -06:00
Mike Griese a9e706c573 fix previewing, again 2021-11-11 09:58:06 -06:00
Mike Griese 2a18d7dae3 This is a checkpoint
* Dismissing a preview with an unfocused appearance is what's really broken here. That's never going to be able to go back to the original table, because the original table will be replaced with the unfocused appearance's table on the dismiss.
    - Going to fix that by using the focused appearance's table by default for the scheme when there's an unfocused appearance.
  * This is a little janky still, we flash the old schemes through on dismiss, which is probably wrong.
2021-11-11 08:28:53 -06:00
Mike Griese ae833a77bd notes, because it's 5pm here 2021-11-10 16:54:31 -06:00
Mike Griese 88f2e64bb3 Transparency is hard 2021-11-10 16:51:09 -06:00
Mike Griese 6e8a2adbd9 MIKE YOU HAVE TEST CASES HERE
This works for opacity for all Terminal cases. Need to still fix conhost.

```json
    "persistedWindowLayouts" :
    [
        {
            "initialPosition" : "149,43",
            "initialSize" :
            {
                "height" : 901.0,
                "width" : 1499.0
            },
            "tabLayout" :
            [
                {
                    "action" : "newTab",
                    "commandline" : "c:\\windows\\system32\\cmd.exe /k colortool.exe -c",
                    "profile" : "One Half Light + cleartype + acrylic",
                    "startingDirectory" : null,
                    "suppressApplicationTitle" : false,
                    "tabTitle" : "One Half Light + cleartype + acrylic"
                },
                {
                    "action" : "splitPane",
                    "commandline" : "c:\\windows\\system32\\cmd.exe /k colortool.exe -c",
                    "profile" : "One Half Light + cleartype + vintage",
                    "size" : 0.5,
                    "split" : "right",
                    "splitMode" : "manual",
                    "startingDirectory" : null,
                    "suppressApplicationTitle" : false,
                    "tabTitle" : "One Half Light + cleartype + vintage"
                },
                {
                    "action" : "moveFocus",
                    "direction" : "previousInOrder"
                },
                {
                    "action" : "splitPane",
                    "commandline" : "c:\\windows\\system32\\cmd.exe /k colortool.exe -c",
                    "profile" : "One Half Light + grayscale + acrylic",
                    "size" : 0.70000004768371582,
                    "split" : "down",
                    "splitMode" : "manual",
                    "startingDirectory" : null,
                    "suppressApplicationTitle" : false,
                    "tabTitle" : "One Half Light + grayscale + acrylic"
                },
                {
                    "action" : "splitPane",
                    "commandline" : "c:\\windows\\system32\\cmd.exe /k colortool.exe -c",
                    "profile" : "One Half Light + cleartype + acrylic(100)",
                    "size" : 0.5,
                    "split" : "down",
                    "splitMode" : "manual",
                    "startingDirectory" : null,
                    "suppressApplicationTitle" : false,
                    "tabTitle" : "One Half Light + cleartype + acrylic(100)"
                },
                {
                    "action" : "moveFocus",
                    "direction" : "nextInOrder"
                },
                {
                    "action" : "splitPane",
                    "commandline" : "c:\\windows\\system32\\cmd.exe /k colortool.exe -c",
                    "profile" : "One Half Light + grayscale + vintage",
                    "size" : 0.70000004768371582,
                    "split" : "down",
                    "splitMode" : "manual",
                    "startingDirectory" : null,
                    "suppressApplicationTitle" : false,
                    "tabTitle" : "One Half Light + grayscale + vintage"
                },
                {
                    "action" : "splitPane",
                    "commandline" : "c:\\windows\\system32\\cmd.exe /k colortool.exe -c",
                    "profile" : "One Half Light + cleartype + vintage(100)",
                    "size" : 0.5,
                    "split" : "down",
                    "splitMode" : "manual",
                    "startingDirectory" : null,
                    "suppressApplicationTitle" : false,
                    "tabTitle" : "One Half Light + cleartype + vintage(100)"
                },
                {
                    "action" : "focusPane",
                    "id" : 5
                },
            ]
        }
    ]
```

    with the following profiles:

    ```json
            {
                "antialiasingMode": "cleartype",
                "colorScheme": "One Half Light",
                "commandline": "c:\\windows\\system32\\cmd.exe /k colortool.exe -c",
                "font":
                {
                    "size": 8
                },
                "guid": "{e7f732da-f5c2-5f52-afd2-82518887a012}",
                "name": "One Half Light + cleartype + acrylic",
                "opacity": 50,
                "useAcrylic": true
            },
            {
                "antialiasingMode": "cleartype",
                "colorScheme": "One Half Light",
                "commandline": "c:\\windows\\system32\\cmd.exe /k colortool.exe -c",
                "font":
                {
                    "size": 8
                },
                "guid": "{e52bc30c-4fa8-5650-9c00-b619544efa5e}",
                "name": "One Half Light + cleartype + vintage",
                "opacity": 50,
                "useAcrylic": false
            },
            {
                "antialiasingMode": "grayscale",
                "colorScheme": "One Half Light",
                "commandline": "c:\\windows\\system32\\cmd.exe /k colortool.exe -c",
                "font":
                {
                    "size": 8
                },
                "guid": "{a870263b-0a3f-561f-82d2-bafc1163f1fc}",
                "name": "One Half Light + grayscale + acrylic",
                "opacity": 50,
                "useAcrylic": true
            },
            {
                "antialiasingMode": "grayscale",
                "colorScheme": "One Half Light",
                "commandline": "c:\\windows\\system32\\cmd.exe /k colortool.exe -c",
                "font":
                {
                    "size": 8
                },
                "guid": "{58a6ffb9-ead3-53ae-a696-c3eb27292578}",
                "name": "One Half Light + grayscale + vintage",
                "opacity": 50,
                "useAcrylic": false
            },
            {
                "antialiasingMode": "cleartype",
                "colorScheme": "One Half Light",
                "commandline": "c:\\windows\\system32\\cmd.exe /k colortool.exe -c",
                "font":
                {
                    "size": 8
                },
                "name": "One Half Light + cleartype + acrylic(100)",
                "opacity": 100,
                "useAcrylic": true
            },
            {
                "antialiasingMode": "cleartype",
                "colorScheme": "One Half Light",
                "commandline": "c:\\windows\\system32\\cmd.exe /k colortool.exe -c",
                "font":
                {
                    "size": 8
                },
                "name": "One Half Light + cleartype + vintage(100)",
                "opacity": 100,
                "useAcrylic": false
            },

    ```
2021-11-10 16:20:13 -06:00
Mike Griese 59c193c22a okay, so it's just vintage(100)+cleartype that doesn't work. Everything else gracefully falls back to grayscale 2021-11-10 15:54:32 -06:00
Mike Griese 713f72e1e5 5/6 transparency cases seem to work. Previewing with unfocused apprearance is broken again. 2021-11-10 15:42:10 -06:00
Mike Griese 5cd8096d42 Revert 5173ea30f5
> yes, but also, no. I tried doing that in 5173ea3, but alas, that doesn't work. There's a lot of places that assumes `IControlSettings requires IControlAppearance`. If you make `ControlSettings` only implement `IControlSettings` and `ICoreSettings`, and not the Appearances as well, then there are various places in UpdateSettings that will crash. (Those could likely be re-written as well, with some pain.)
>
> In almost all cases where we're using a `IControlSettings` as an Appearance, we're only interested in the `FocusedAppearance`'s value.
2021-11-10 12:54:45 -06:00
Mike Griese 147101f833 Whoops, needed this earlier 2021-11-10 12:40:40 -06:00
Mike Griese 5173ea30f5 much of this appearance code was unneeded 2021-11-10 12:29:34 -06:00
Mike Griese 9eeea4a9d0 The simple PR feedback 2021-11-10 11:32:31 -06:00
Mike Griese d51c2cff35 Merge remote-tracking branch 'origin/main' into dev/migrie/oop/ragnarok 2021-11-10 10:27:35 -06:00
Mike Griese 83e7aead57 Merge remote-tracking branch 'origin/main' into dev/migrie/oop/ragnarok 2021-11-02 16:56:42 -05:00
Mike Griese 6da5d79d47 Merge remote-tracking branch 'origin/main' into dev/migrie/oop/ragnarok 2021-11-01 16:23:36 -05:00
Mike Griese 51486a4168 Merge remote-tracking branch 'origin/main' into dev/migrie/oop/ragnarok 2021-10-28 08:49:38 -05:00
Mike Griese f111c6d72d thanks spell bot 2021-10-26 14:45:35 -05:00
Mike Griese f087dd8236 no more todos. Bot, tell me what I typod 2021-10-26 12:49:21 -05:00
Mike Griese bf9bf0e138 cleanup two of the remaining TODOs 2021-10-26 12:44:03 -05:00
Mike Griese 7c288517a5 this fixes the weird lock that we really really don't need anymore 2021-10-26 12:41:22 -05:00
Mike Griese 8c7ce77811 fix the local tests too 2021-10-26 12:30:49 -05:00
Mike Griese 01cef2f3dc fix control unit tets 2021-10-26 11:51:53 -05:00
Mike Griese 4a700cd1cc Merge remote-tracking branch 'origin/main' into dev/migrie/oop/ragnarok 2021-10-26 11:36:10 -05:00
Mike Griese 217742c1ff Some of these calls were duplicates. Some were redundant. Overall cleanup of these guys. 2021-10-26 10:59:50 -05:00
Mike Griese 48ca704816 More cleanup. Forgot to lock here. 2021-10-26 10:40:22 -05:00
Mike Griese 634b6854dc fix a bug with toggling the retro effects from the palette 2021-10-26 10:23:26 -05:00
Mike Griese 28cbad1470 get the tests compiling again 2021-10-26 09:27:48 -05:00
Mike Griese 94f4ef5601 lots of cleanup 2021-10-26 09:09:05 -05:00
Mike Griese 6babb4e73a cleanup 2021-10-26 08:59:04 -05:00
Mike Griese 282c03c374 whoop, it works! 2021-10-26 07:36:29 -05:00
Mike Griese 916096643e This almost works for previewing, but I fudged something up with the backgrounds and now they're totally transparent 2021-10-26 07:19:18 -05:00
Mike Griese e3a50cfdee turns out we didn't need all them fancy overrides 2021-10-21 16:11:57 -05:00
Mike Griese 1aa2849d94 you've seen WINRT_PROPERTY now get ready for RUNTIME_PROPERTY
and as soon ad I typed that out I realized that WINRT_PROPERTY already has
    setters and setting an optional override gets me nothing

    sure I could stealth the new value in underneath the runtime value, so
    reloading the settings doesn't reset font size, colors, etc

    I could

    but it sure does feel like overkill for "refactor but don't change anything"
2021-10-21 15:53:22 -05:00
Mike Griese 17829f438b This is how I wanted to solve the color scheme setting, previewing, but UpdateAppearance ends up getting called immediately after so it blows it away. Dustin had a crazy idea... 2021-10-21 15:35:27 -05:00
Mike Griese 888e1572d2 more cleanup, 5 todo!s left 2021-10-20 16:33:22 -05:00
Mike Griese 4912b65967 mostly cleanup, 7 TODOs remain 2021-10-20 12:49:55 -05:00
Mike Griese 03711944f1 okay this seems to fix opacity & cleartype in all cases 2021-10-20 11:50:50 -05:00
Mike Griese 70b9f8ce5f This is the start of fixing the opacity roundtripping weirdness 2021-10-20 10:47:12 -05:00
Mike Griese a9de82e4ee saving the settings works again 2021-10-20 08:18:51 -05:00
Mike Griese 4f7e883673 This crashes substantially less frequently 2021-10-19 12:44:51 -05:00
Mike Griese 31e799859f this builds at least 2021-10-19 11:27:26 -05:00
Mike Griese 1413d0145a Merge remote-tracking branch 'origin/main' into dev/migrie/oop/ragnarok 2021-10-14 15:55:18 -05:00
Mike Griese fbba74e89b I think we're going to have to cut this 2021-10-14 15:47:34 -05:00
Mike Griese 4a1baf0006 I think I needed this to get it to build. Or I started breaknig something. Idk, I wrote this a few days ago, I just need this clone for testing so `git commit` 2021-09-30 10:46:39 -05:00
Mike Griese c26dd6b1db This works better than it has any business doing. Plemty of bugs, but a good enough start 2021-09-28 13:00:52 -05:00
Mike Griese c7536edfa8 This says there's only one build error in Terminal.Control.Lib but that can't be right 2021-09-28 11:36:21 -05:00
Mike Griese 7fc2f10bbd move to a common header 2021-09-23 17:08:40 -05:00
Mike Griese 4b18bb415e missed one 2021-09-23 16:49:35 -05:00
Mike Griese d6989ec9d1 this is wild 2021-09-23 16:46:05 -05:00
Mike Griese 981d8cc9c8 This is a crazy idea but if it works, it'll be a game changer 2021-09-23 16:31:31 -05:00
Mike Griese dad065e0fe make this a macro in case we want to reuse this 2021-09-23 15:45:25 -05:00
Mike Griese 43ec102343 blindly make control settings read-only, there's only 2 build breaks? 2021-09-23 14:45:54 -05:00
39 changed files with 876 additions and 504 deletions

View File

@ -55,8 +55,12 @@ namespace SettingsModelLocalTests
TerminalSettings settings;
VERIFY_IS_NOT_NULL(settings);
auto oldFontSize = settings.FontSize();
settings.FontSize(oldFontSize + 5);
auto newFontSize = settings.FontSize();
auto selfSettings = winrt::make_self<implementation::TerminalSettings>();
VERIFY_ARE_EQUAL(oldFontSize, selfSettings->FontSize());
selfSettings->FontSize(oldFontSize + 5);
auto newFontSize = selfSettings->FontSize();
VERIFY_ARE_NOT_EQUAL(oldFontSize, newFontSize);
}

View File

@ -90,7 +90,6 @@ namespace TerminalAppLocalTests
TEST_METHOD(TestWindowRenameSuccessful);
TEST_METHOD(TestWindowRenameFailure);
TEST_METHOD(TestControlSettingsHasParent);
TEST_METHOD(TestPreviewCommitScheme);
TEST_METHOD(TestPreviewDismissScheme);
TEST_METHOD(TestPreviewSchemeWhilePreviewing);
@ -134,10 +133,6 @@ namespace TerminalAppLocalTests
// Just creating it is enough to know that everything is working.
TerminalSettings settings;
VERIFY_IS_NOT_NULL(settings);
auto oldFontSize = settings.FontSize();
settings.FontSize(oldFontSize + 5);
auto newFontSize = settings.FontSize();
VERIFY_ARE_NOT_EQUAL(oldFontSize, newFontSize);
}
void TabTests::TryCreateConnectionType()
@ -1297,25 +1292,6 @@ namespace TerminalAppLocalTests
});
}
void TabTests::TestControlSettingsHasParent()
{
Log::Comment(L"Ensure that when we create a control, it always has a parent TerminalSettings");
auto page = _commonSetup();
VERIFY_IS_NOT_NULL(page);
TestOnUIThread([&page]() {
const auto& activeControl{ page->_GetActiveControl() };
VERIFY_IS_NOT_NULL(activeControl);
const auto& controlSettings = activeControl.Settings().as<TerminalSettings>();
VERIFY_IS_NOT_NULL(controlSettings);
const auto& originalSettings = controlSettings.GetParent();
VERIFY_IS_NOT_NULL(originalSettings);
});
}
void TabTests::TestPreviewCommitScheme()
{
Log::Comment(L"Preview a color scheme. Make sure it's applied, then committed accordingly");
@ -1327,12 +1303,9 @@ namespace TerminalAppLocalTests
const auto& activeControl{ page->_GetActiveControl() };
VERIFY_IS_NOT_NULL(activeControl);
const auto& controlSettings = activeControl.Settings().as<TerminalSettings>();
const auto& controlSettings = activeControl.Settings();
VERIFY_IS_NOT_NULL(controlSettings);
const auto& originalSettings = controlSettings.GetParent();
VERIFY_IS_NOT_NULL(originalSettings);
VERIFY_ARE_EQUAL(til::color{ 0xff0c0c0c }, controlSettings.DefaultBackground());
});
@ -1346,17 +1319,12 @@ namespace TerminalAppLocalTests
const auto& activeControl{ page->_GetActiveControl() };
VERIFY_IS_NOT_NULL(activeControl);
const auto& controlSettings = activeControl.Settings().as<TerminalSettings>();
const auto& controlSettings = activeControl.Settings();
VERIFY_IS_NOT_NULL(controlSettings);
const auto& previewSettings = controlSettings.GetParent();
VERIFY_IS_NOT_NULL(previewSettings);
const auto& originalSettings = previewSettings.GetParent();
VERIFY_IS_NOT_NULL(originalSettings);
Log::Comment(L"Color should be changed to the preview");
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
// And we should have stored a function to revert the change.
VERIFY_ARE_EQUAL(1u, page->_restorePreviewFuncs.size());
});
@ -1373,20 +1341,22 @@ namespace TerminalAppLocalTests
const auto& activeControl{ page->_GetActiveControl() };
VERIFY_IS_NOT_NULL(activeControl);
const auto& controlSettings = activeControl.Settings().as<TerminalSettings>();
const auto& controlSettings = activeControl.Settings();
VERIFY_IS_NOT_NULL(controlSettings);
const auto& originalSettings = controlSettings.GetParent();
VERIFY_IS_NOT_NULL(originalSettings);
const auto& grandparentSettings = originalSettings.GetParent();
VERIFY_IS_NULL(grandparentSettings);
Log::Comment(L"Color should be changed");
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
// After preview there should be no more restore functions to execute.
VERIFY_ARE_EQUAL(0u, page->_restorePreviewFuncs.size());
});
Log::Comment(L"Sleep to let events propagate");
// If you don't do this, we will _sometimes_ crash as we're tearing down
// the control from this test as we start the next one. We crash
// somewhere in the CursorPositionChanged handler. It's annoying, but
// this works.
Sleep(250);
}
void TabTests::TestPreviewDismissScheme()
@ -1400,12 +1370,9 @@ namespace TerminalAppLocalTests
const auto& activeControl{ page->_GetActiveControl() };
VERIFY_IS_NOT_NULL(activeControl);
const auto& controlSettings = activeControl.Settings().as<TerminalSettings>();
const auto& controlSettings = activeControl.Settings();
VERIFY_IS_NOT_NULL(controlSettings);
const auto& originalSettings = controlSettings.GetParent();
VERIFY_IS_NOT_NULL(originalSettings);
VERIFY_ARE_EQUAL(til::color{ 0xff0c0c0c }, controlSettings.DefaultBackground());
});
@ -1419,15 +1386,9 @@ namespace TerminalAppLocalTests
const auto& activeControl{ page->_GetActiveControl() };
VERIFY_IS_NOT_NULL(activeControl);
const auto& controlSettings = activeControl.Settings().as<TerminalSettings>();
const auto& controlSettings = activeControl.Settings();
VERIFY_IS_NOT_NULL(controlSettings);
const auto& previewSettings = controlSettings.GetParent();
VERIFY_IS_NOT_NULL(previewSettings);
const auto& originalSettings = previewSettings.GetParent();
VERIFY_IS_NOT_NULL(originalSettings);
Log::Comment(L"Color should be changed to the preview");
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
});
@ -1441,18 +1402,14 @@ namespace TerminalAppLocalTests
const auto& activeControl{ page->_GetActiveControl() };
VERIFY_IS_NOT_NULL(activeControl);
const auto& controlSettings = activeControl.Settings().as<TerminalSettings>();
const auto& controlSettings = activeControl.Settings();
VERIFY_IS_NOT_NULL(controlSettings);
const auto& originalSettings = controlSettings.GetParent();
VERIFY_IS_NOT_NULL(originalSettings);
const auto& grandparentSettings = originalSettings.GetParent();
VERIFY_IS_NULL(grandparentSettings);
Log::Comment(L"Color should be the same as it originally was");
VERIFY_ARE_EQUAL(til::color{ 0xff0c0c0c }, controlSettings.DefaultBackground());
});
Log::Comment(L"Sleep to let events propagate");
Sleep(250);
}
void TabTests::TestPreviewSchemeWhilePreviewing()
@ -1468,12 +1425,9 @@ namespace TerminalAppLocalTests
const auto& activeControl{ page->_GetActiveControl() };
VERIFY_IS_NOT_NULL(activeControl);
const auto& controlSettings = activeControl.Settings().as<TerminalSettings>();
const auto& controlSettings = activeControl.Settings();
VERIFY_IS_NOT_NULL(controlSettings);
const auto& originalSettings = controlSettings.GetParent();
VERIFY_IS_NOT_NULL(originalSettings);
VERIFY_ARE_EQUAL(til::color{ 0xff0c0c0c }, controlSettings.DefaultBackground());
});
@ -1487,15 +1441,9 @@ namespace TerminalAppLocalTests
const auto& activeControl{ page->_GetActiveControl() };
VERIFY_IS_NOT_NULL(activeControl);
const auto& controlSettings = activeControl.Settings().as<TerminalSettings>();
const auto& controlSettings = activeControl.Settings();
VERIFY_IS_NOT_NULL(controlSettings);
const auto& previewSettings = controlSettings.GetParent();
VERIFY_IS_NOT_NULL(previewSettings);
const auto& originalSettings = previewSettings.GetParent();
VERIFY_IS_NOT_NULL(originalSettings);
Log::Comment(L"Color should be changed to the preview");
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
});
@ -1510,15 +1458,9 @@ namespace TerminalAppLocalTests
const auto& activeControl{ page->_GetActiveControl() };
VERIFY_IS_NOT_NULL(activeControl);
const auto& controlSettings = activeControl.Settings().as<TerminalSettings>();
const auto& controlSettings = activeControl.Settings();
VERIFY_IS_NOT_NULL(controlSettings);
const auto& previewSettings = controlSettings.GetParent();
VERIFY_IS_NOT_NULL(previewSettings);
const auto& originalSettings = previewSettings.GetParent();
VERIFY_IS_NOT_NULL(originalSettings);
Log::Comment(L"Color should be changed to the preview");
VERIFY_ARE_EQUAL(til::color{ 0xffFAFAFA }, controlSettings.DefaultBackground());
});
@ -1535,18 +1477,14 @@ namespace TerminalAppLocalTests
const auto& activeControl{ page->_GetActiveControl() };
VERIFY_IS_NOT_NULL(activeControl);
const auto& controlSettings = activeControl.Settings().as<TerminalSettings>();
const auto& controlSettings = activeControl.Settings();
VERIFY_IS_NOT_NULL(controlSettings);
const auto& originalSettings = controlSettings.GetParent();
VERIFY_IS_NOT_NULL(originalSettings);
const auto& grandparentSettings = originalSettings.GetParent();
VERIFY_IS_NULL(grandparentSettings);
Log::Comment(L"Color should be changed");
VERIFY_ARE_EQUAL(til::color{ 0xffFAFAFA }, controlSettings.DefaultBackground());
});
Log::Comment(L"Sleep to let events propagate");
Sleep(250);
}
void TabTests::TestClampSwitchToTab()

View File

@ -67,8 +67,12 @@ namespace winrt::TerminalApp::implementation
// - <none>
void TerminalPage::_EndPreviewColorScheme()
{
for (const auto& f : _restorePreviewFuncs)
// Apply the reverts in reverse order - If we had multiple previews
// stacked on top of each other, then this will ensure the first one in
// is the last one out.
for (auto i{ _restorePreviewFuncs.rbegin() }; i < _restorePreviewFuncs.rend(); i++)
{
auto f = *i;
f();
}
_restorePreviewFuncs.clear();
@ -90,59 +94,18 @@ namespace winrt::TerminalApp::implementation
{
if (const auto& scheme{ _settings.GlobalSettings().ColorSchemes().TryLookup(args.SchemeName()) })
{
// Clear the saved preview funcs because we don't need to add a restore each time
// the preview color changes, we only need to be able to restore the last one.
_restorePreviewFuncs.clear();
_ApplyToActiveControls([&](const auto& control) {
// Get the settings of the focused control and stash them
const auto& controlSettings = control.Settings().as<TerminalSettings>();
// Make sure to recurse up to the root - if you're doing
// this while you're currently previewing a SetColorScheme
// action, then the parent of the control's settings is _the
// last preview TerminalSettings we inserted! We don't want
// to save that one!
auto originalSettings = controlSettings.GetParent();
while (originalSettings.GetParent() != nullptr)
{
originalSettings = originalSettings.GetParent();
}
// Create a new child for those settings
TerminalSettingsCreateResult fake{ originalSettings };
const auto& childStruct = TerminalSettings::CreateWithParent(fake);
// Modify the child to have the applied color scheme
childStruct.DefaultSettings().ApplyColorScheme(scheme);
// Stash a copy of the current scheme.
auto originalScheme{ control.ColorScheme() };
// Insert that new child as the parent of the control's settings
controlSettings.SetParent(childStruct.DefaultSettings());
control.UpdateSettings();
// Apply the new scheme.
control.ColorScheme(scheme.ToCoreScheme());
// Take a copy of the inputs, since they are pointers anyways.
// Each control will emplace a revert into the
// _restorePreviewFuncs for itself.
_restorePreviewFuncs.emplace_back([=]() {
// Get the runtime settings of the focused control
const auto& controlSettings{ control.Settings().as<TerminalSettings>() };
// Get the control's root settings, the ones that we actually
// assigned to it.
auto parentSettings{ controlSettings.GetParent() };
while (parentSettings.GetParent() != nullptr)
{
parentSettings = parentSettings.GetParent();
}
// If the root settings are the same as the ones we stashed,
// then reset the parent of the runtime settings to the stashed
// settings. This condition might be false if the settings
// hot-reloaded while the palette was open. In that case, we
// don't want to reset the settings to what they were _before_
// the hot-reload.
if (originalSettings == parentSettings)
{
// Set the original settings as the parent of the control's settings
control.Settings().as<TerminalSettings>().SetParent(originalSettings);
}
control.UpdateSettings();
// On dismiss, restore the original scheme.
control.ColorScheme(originalScheme);
});
});
}

View File

@ -451,28 +451,7 @@ namespace winrt::TerminalApp::implementation
if (const auto scheme = _settings.GlobalSettings().ColorSchemes().TryLookup(realArgs.SchemeName()))
{
const auto res = _ApplyToActiveControls([&](auto& control) {
// Start by getting the current settings of the control
auto controlSettings = control.Settings().as<TerminalSettings>();
auto parentSettings = controlSettings;
// Those are the _runtime_ settings however. What we
// need to do is:
//
// 1. Blow away any colors set in the runtime settings.
// 2. Apply the color scheme to the parent settings.
//
// 1 is important to make sure that the effects of
// something like `colortool` are cleared when setting
// the scheme.
if (controlSettings.GetParent() != nullptr)
{
parentSettings = controlSettings.GetParent();
}
// ApplyColorScheme(nullptr) will clear the old color scheme.
controlSettings.ApplyColorScheme(nullptr);
parentSettings.ApplyColorScheme(scheme);
control.UpdateSettings();
control.ColorScheme(scheme.ToCoreScheme());
});
args.Handled(res);
}

View File

@ -125,7 +125,7 @@ NewTerminalArgs Pane::GetTerminalArgsForPane() const
assert(_IsLeaf());
NewTerminalArgs args{};
auto controlSettings = _control.Settings().as<TerminalSettings>();
auto controlSettings = _control.Settings();
args.Profile(controlSettings.ProfileName());
// If we know the user's working directory use it instead of the profile.
@ -156,16 +156,13 @@ NewTerminalArgs Pane::GetTerminalArgsForPane() const
args.TabColor(winrt::Windows::Foundation::IReference<winrt::Windows::UI::Color>(c));
}
if (controlSettings.AppliedColorScheme())
{
auto name = controlSettings.AppliedColorScheme().Name();
// Only save the color scheme if it is different than the profile color
// scheme to not override any other profile appearance choices.
if (_profile.DefaultAppearance().ColorSchemeName() != name)
{
args.ColorScheme(name);
}
}
// TODO:GH#9800 - we used to be able to persist the color scheme that a
// TermControl was initialized with, by name. With the change to having the
// control own its own copy of its settings, this isn't possible anymore.
//
// We may be able to get around this by storing the Name in the Core::Scheme
// object. That would work for schemes set by the Terminal, but not ones set
// by VT, but that seems good enough.
return args;
}
@ -1459,21 +1456,8 @@ void Pane::UpdateSettings(const TerminalSettingsCreateResult& settings, const Pr
assert(_IsLeaf());
_profile = profile;
auto controlSettings = _control.Settings().as<TerminalSettings>();
// Update the parent of the control's settings object (and not the object itself) so
// that any overrides made by the control don't get affected by the reload
controlSettings.SetParent(settings.DefaultSettings());
auto unfocusedSettings{ settings.UnfocusedSettings() };
if (unfocusedSettings)
{
// Note: the unfocused settings needs to be entirely unchanged _except_ we need to
// set its parent to the settings object that lives in the control. This is because
// the overrides made by the control live in that settings object, so we want to make
// sure the unfocused settings inherit from that.
unfocusedSettings.SetParent(controlSettings);
}
_control.UnfocusedAppearance(unfocusedSettings);
_control.UpdateSettings();
_control.UpdateControlSettings(settings.DefaultSettings(), settings.UnfocusedSettings());
}
// Method Description:

View File

@ -2123,13 +2123,10 @@ namespace winrt::TerminalApp::implementation
TermControl TerminalPage::_InitControl(const TerminalSettingsCreateResult& settings, const ITerminalConnection& connection)
{
// Give term control a child of the settings so that any overrides go in the child
// This way, when we do a settings reload we just update the parent and the overrides remain
const auto child = TerminalSettings::CreateWithParent(settings);
TermControl term{ child.DefaultSettings(), connection };
term.UnfocusedAppearance(child.UnfocusedSettings()); // It is okay for the unfocused settings to be null
// Do any initialization that needs to apply to _every_ TermControl we
// create here.
// TermControl will copy the settings out of the settings passed to it.
TermControl term{ settings.DefaultSettings(), settings.UnfocusedSettings(), connection };
return term;
}

View File

@ -0,0 +1,49 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
--*/
#pragma once
#include "../../inc/cppwinrt_utils.h"
#include "../../inc/ControlProperties.h"
#include <DefaultSettings.h>
#include <conattrs.hpp>
namespace winrt::Microsoft::Terminal::Control::implementation
{
struct ControlAppearance : public winrt::implements<ControlAppearance, Microsoft::Terminal::Core::ICoreAppearance, Microsoft::Terminal::Control::IControlAppearance>
{
#define SETTINGS_GEN(type, name, ...) WINRT_PROPERTY(type, name, __VA_ARGS__);
CORE_APPEARANCE_SETTINGS(SETTINGS_GEN)
CONTROL_APPEARANCE_SETTINGS(SETTINGS_GEN)
#undef SETTINGS_GEN
private:
// Color Table is special because it's an array
std::array<winrt::Microsoft::Terminal::Core::Color, COLOR_TABLE_SIZE> _ColorTable;
public:
winrt::Microsoft::Terminal::Core::Color GetColorTableEntry(int32_t index) noexcept
{
return _ColorTable.at(index);
}
void SetColorTableEntry(int32_t index,
winrt::Microsoft::Terminal::Core::Color color) noexcept
{
_ColorTable.at(index) = color;
}
ControlAppearance(Control::IControlAppearance appearance)
{
#define COPY_SETTING(type, name, ...) _##name = appearance.name();
CORE_APPEARANCE_SETTINGS(COPY_SETTING)
CONTROL_APPEARANCE_SETTINGS(COPY_SETTING)
#undef COPY_SETTING
for (size_t i = 0; i < _ColorTable.size(); i++)
{
_ColorTable[i] = appearance.GetColorTableEntry(static_cast<int32_t>(i));
}
}
};
}

View File

@ -56,15 +56,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return initialized;
}
ControlCore::ControlCore(IControlSettings settings,
ControlCore::ControlCore(Control::IControlSettings settings,
Control::IControlAppearance unfocusedAppearance,
TerminalConnection::ITerminalConnection connection) :
_connection{ connection },
_settings{ settings },
_desiredFont{ DEFAULT_FONT_FACE, 0, DEFAULT_FONT_WEIGHT, { 0, DEFAULT_FONT_SIZE }, CP_UTF8 },
_actualFont{ DEFAULT_FONT_FACE, 0, DEFAULT_FONT_WEIGHT, { 0, DEFAULT_FONT_SIZE }, CP_UTF8, false }
{
_EnsureStaticInitialization();
_settings = winrt::make_self<implementation::ControlSettings>(settings, unfocusedAppearance);
_terminal = std::make_unique<::Microsoft::Terminal::Core::Terminal>();
// Subscribe to the connection's disconnected event and call our connection closed handlers.
@ -80,7 +82,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
});
// GH#8969: pre-seed working directory to prevent potential races
_terminal->SetWorkingDirectory(_settings.StartingDirectory());
_terminal->SetWorkingDirectory(_settings->StartingDirectory());
auto pfnCopyToClipboard = std::bind(&ControlCore::_terminalCopyToClipboard, this, std::placeholders::_1);
_terminal->SetCopyToClipboardCallback(pfnCopyToClipboard);
@ -187,7 +189,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
});
UpdateSettings(settings);
UpdateSettings(settings, unfocusedAppearance);
}
ControlCore::~ControlCore()
@ -226,7 +228,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return false;
}
if (Feature_AtlasEngine::IsEnabled() && _settings.UseAtlasEngine())
if (Feature_AtlasEngine::IsEnabled() && _settings->UseAtlasEngine())
{
_renderEngine = std::make_unique<::Microsoft::Console::Render::AtlasEngine>();
}
@ -252,7 +254,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
LOG_IF_FAILED(_renderEngine->SetWindowSize({ viewInPixels.Width(), viewInPixels.Height() }));
// Update DxEngine's SelectionBackground
_renderEngine->SetSelectionBackground(til::color{ _settings.SelectionBackground() });
_renderEngine->SetSelectionBackground(til::color{ _settings->SelectionBackground() });
const auto vp = _renderEngine->GetViewportInCharacters(viewInPixels);
const auto width = vp.Width();
@ -260,10 +262,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_connection.Resize(height, width);
// Override the default width and height to match the size of the swapChainPanel
_settings.InitialCols(width);
_settings.InitialRows(height);
_settings->InitialCols(width);
_settings->InitialRows(height);
_terminal->CreateFromSettings(_settings, *_renderer);
_terminal->CreateFromSettings(*_settings, *_renderer);
// IMPORTANT! Set this callback up sooner than later. If we do it
// after Enable, then it'll be possible to paint the frame once
@ -275,18 +277,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// We do this after we initially set the swapchain so as to avoid unnecessary callbacks (and locking problems)
_renderEngine->SetCallback(std::bind(&ControlCore::_renderEngineSwapChainChanged, this));
_renderEngine->SetRetroTerminalEffect(_settings.RetroTerminalEffect());
_renderEngine->SetPixelShaderPath(_settings.PixelShaderPath());
_renderEngine->SetForceFullRepaintRendering(_settings.ForceFullRepaintRendering());
_renderEngine->SetSoftwareRendering(_settings.SoftwareRendering());
_renderEngine->SetIntenseIsBold(_settings.IntenseIsBold());
_renderEngine->SetRetroTerminalEffect(_settings->RetroTerminalEffect());
_renderEngine->SetPixelShaderPath(_settings->PixelShaderPath());
_renderEngine->SetForceFullRepaintRendering(_settings->ForceFullRepaintRendering());
_renderEngine->SetSoftwareRendering(_settings->SoftwareRendering());
_renderEngine->SetIntenseIsBold(_settings->IntenseIsBold());
_updateAntiAliasingMode();
// GH#5098: Inform the engine of the opacity of the default text background.
// GH#11315: Always do this, even if they don't have acrylic on.
const auto backgroundIsOpaque = _settings.Opacity() == 1.0 && _settings.BackgroundImage().empty();
_renderEngine->SetDefaultTextBackgroundOpacity(static_cast<float>(backgroundIsOpaque));
_renderEngine->EnableTransparentBackground(_isBackgroundTransparent());
THROW_IF_FAILED(_renderEngine->Enable());
@ -444,14 +445,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return;
}
auto newOpacity = std::clamp(_settings.Opacity() + adjustment,
auto newOpacity = std::clamp(Opacity() + adjustment,
0.0,
1.0);
// GH#5098: Inform the engine of the new opacity of the default text background.
SetBackgroundOpacity(::base::saturated_cast<float>(newOpacity));
_settings.Opacity(newOpacity);
auto lock = _terminal->LockForWriting();
// Update our runtime opacity value
Opacity(newOpacity);
// GH#11285 - If the user is on Windows 10, and they changed the
// transparency of the control s.t. it should be partially opaque, then
@ -461,7 +461,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// is what the Terminal did prior to 1.12.
if (!IsVintageOpacityAvailable())
{
_settings.UseAcrylic(newOpacity < 1.0);
_runtimeUseAcrylic = newOpacity < 1.0;
}
// Update the renderer as well. It might need to fall back from
// cleartype -> grayscale if the BG is transparent / acrylic.
if (_renderEngine)
{
_renderEngine->EnableTransparentBackground(_isBackgroundTransparent());
}
auto eventArgs = winrt::make_self<TransparencyChangedEventArgs>(newOpacity);
@ -476,7 +483,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// specify a custom pixel shader, manually enable the legacy retro
// effect first. This will ensure that a toggle off->on will still work,
// even if they currently have retro effect off.
if (_settings.PixelShaderPath().empty() && !_renderEngine->GetRetroTerminalEffect())
if (_settings->PixelShaderPath().empty() && !_renderEngine->GetRetroTerminalEffect())
{
// SetRetroTerminalEffect to true will enable the effect. In this
// case, the shader effect will already be disabled (because neither
@ -586,24 +593,27 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Method Description:
// - Updates the settings of the current terminal.
// - INVARIANT: This method can only be called if the caller DOES NOT HAVE writing lock on the terminal.
void ControlCore::UpdateSettings(const IControlSettings& settings)
void ControlCore::UpdateSettings(const IControlSettings& settings, const IControlAppearance& newAppearance)
{
_settings = winrt::make_self<implementation::ControlSettings>(settings, newAppearance);
auto lock = _terminal->LockForWriting();
_settings = settings;
_runtimeOpacity = std::nullopt;
_runtimeUseAcrylic = std::nullopt;
// GH#11285 - If the user is on Windows 10, and they wanted opacity, but
// didn't explicitly request acrylic, then opt them in to acrylic.
// On Windows 11+, this isn't needed, because we can have vintage opacity.
if (!IsVintageOpacityAvailable() && _settings.Opacity() < 1.0 && !_settings.UseAcrylic())
if (!IsVintageOpacityAvailable() && _settings->Opacity() < 1.0 && !_settings->UseAcrylic())
{
_settings.UseAcrylic(true);
_runtimeUseAcrylic = true;
}
// Initialize our font information.
const auto fontFace = _settings.FontFace();
const short fontHeight = ::base::saturated_cast<short>(_settings.FontSize());
const auto fontWeight = _settings.FontWeight();
const auto fontFace = _settings->FontFace();
const short fontHeight = ::base::saturated_cast<short>(_settings->FontSize());
const auto fontWeight = _settings->FontWeight();
// The font width doesn't terribly matter, we'll only be using the
// height to look it up
// The other params here also largely don't matter.
@ -615,7 +625,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_desiredFont = { _actualFont };
// Update the terminal core with its new Core settings
_terminal->UpdateSettings(_settings);
_terminal->UpdateSettings(*_settings);
if (!_initializedTerminal)
{
@ -624,8 +634,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return;
}
_renderEngine->SetForceFullRepaintRendering(_settings.ForceFullRepaintRendering());
_renderEngine->SetSoftwareRendering(_settings.SoftwareRendering());
_renderEngine->SetForceFullRepaintRendering(_settings->ForceFullRepaintRendering());
_renderEngine->SetSoftwareRendering(_settings->SoftwareRendering());
// Inform the renderer of our opacity
_renderEngine->EnableTransparentBackground(_isBackgroundTransparent());
_updateAntiAliasingMode();
@ -642,21 +654,21 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Method Description:
// - Updates the appearance of the current terminal.
// - INVARIANT: This method can only be called if the caller DOES NOT HAVE writing lock on the terminal.
void ControlCore::UpdateAppearance(const IControlAppearance& newAppearance)
void ControlCore::ApplyAppearance(const bool& focused)
{
auto lock = _terminal->LockForWriting();
const auto& newAppearance{ focused ? _settings->FocusedAppearance() : _settings->UnfocusedAppearance() };
// Update the terminal core with its new Core settings
_terminal->UpdateAppearance(newAppearance);
_terminal->UpdateAppearance(*newAppearance);
// Update DxEngine settings under the lock
if (_renderEngine)
{
// Update DxEngine settings under the lock
_renderEngine->SetSelectionBackground(til::color{ newAppearance.SelectionBackground() });
_renderEngine->SetRetroTerminalEffect(newAppearance.RetroTerminalEffect());
_renderEngine->SetPixelShaderPath(newAppearance.PixelShaderPath());
_renderEngine->SetIntenseIsBold(_settings.IntenseIsBold());
_renderEngine->SetSelectionBackground(til::color{ newAppearance->SelectionBackground() });
_renderEngine->SetRetroTerminalEffect(newAppearance->RetroTerminalEffect());
_renderEngine->SetPixelShaderPath(newAppearance->PixelShaderPath());
_renderEngine->SetIntenseIsBold(_settings->IntenseIsBold());
_renderer->TriggerRedrawAll();
}
}
@ -664,8 +676,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void ControlCore::_updateAntiAliasingMode()
{
D2D1_TEXT_ANTIALIAS_MODE mode;
switch (_settings.AntialiasingMode())
// Update DxEngine's AntialiasingMode
switch (_settings->AntialiasingMode())
{
case TextAntialiasingMode::Cleartype:
mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
@ -701,7 +713,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
if (_renderEngine)
{
std::unordered_map<std::wstring_view, uint32_t> featureMap;
if (const auto fontFeatures = _settings.FontFeatures())
if (const auto fontFeatures = _settings->FontFeatures())
{
featureMap.reserve(fontFeatures.Size());
@ -711,7 +723,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
}
std::unordered_map<std::wstring_view, float> axesMap;
if (const auto fontAxes = _settings.FontAxes())
if (const auto fontAxes = _settings->FontAxes())
{
axesMap.reserve(fontAxes.Size());
@ -753,8 +765,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
// Make sure we have a non-zero font size
const auto newSize = std::max<short>(gsl::narrow_cast<short>(fontSize), 1);
const auto fontFace = _settings.FontFace();
const auto fontWeight = _settings.FontWeight();
const auto fontFace = _settings->FontFace();
const auto fontWeight = _settings->FontWeight();
_actualFont = { fontFace, 0, fontWeight.Weight, { 0, newSize }, CP_UTF8, false };
_actualFontFaceName = { fontFace };
_desiredFont = { _actualFont };
@ -779,7 +791,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - none
void ControlCore::ResetFontSize()
{
_setFontSize(_settings.FontSize());
_setFontSize(_settings->FontSize());
}
// Method Description:
@ -991,7 +1003,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
TextBuffer::GenHTML(bufferData,
_actualFont.GetUnscaledSize().Y,
_actualFont.GetFaceName(),
til::color{ _settings.DefaultBackground() }) :
til::color{ _settings->DefaultBackground() }) :
"";
// convert to RTF format
@ -999,10 +1011,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
TextBuffer::GenRTF(bufferData,
_actualFont.GetUnscaledSize().Y,
_actualFont.GetFaceName(),
til::color{ _settings.DefaultBackground() }) :
til::color{ _settings->DefaultBackground() }) :
"";
if (!_settings.CopyOnSelect())
if (!_settings->CopyOnSelect())
{
_terminal->ClearSelection();
_renderer->TriggerSelection();
@ -1089,7 +1101,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
til::color ControlCore::BackgroundColor() const
{
return _terminal->GetDefaultBackground();
// The Terminal internally stores it's BG with 0 opacity, so as to allow
// DX to paint the BG color transparently. We however don't want to leak
// that implementation detail.
return _terminal->GetDefaultBackground().with_alpha(0xff);
}
// Method Description:
@ -1246,7 +1261,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
bool ControlCore::CopyOnSelect() const
{
return _settings.CopyOnSelect();
return _settings->CopyOnSelect();
}
Windows::Foundation::Collections::IVector<winrt::hstring> ControlCore::SelectedText(bool trimTrailingWhitespace) const
@ -1304,16 +1319,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
}
void ControlCore::SetBackgroundOpacity(const double opacity)
{
if (_renderEngine)
{
auto lock = _terminal->LockForWriting();
const auto backgroundIsOpaque = opacity == 1.0 && _settings.BackgroundImage().empty();
_renderEngine->SetDefaultTextBackgroundOpacity(static_cast<float>(backgroundIsOpaque));
}
}
// Method Description:
// - Asynchronously close our connection. The Connection will likely wait
// until the attached process terminates before Close returns. If that's
@ -1599,4 +1604,125 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return VerifyVersionInfoW(&osver, VER_BUILDNUMBER, dwlConditionMask) != FALSE;
}
Core::Scheme ControlCore::ColorScheme() const noexcept
{
Core::Scheme s;
// This part is definitely a hack.
//
// This function is usually used by the "Preview Color Scheme"
// functionality in TerminalPage. If we've got an unfocused appearance,
// then we've applied that appearance before this is even getting called
// (because the command palette is open with focus on top of us). If we
// return the _current_ colors now, we'll return out the _unfocused_
// colors. If we do that, and the user dismisses the command palette,
// then the scheme that will get restored is the _unfocused_ one, which
// is not what we want.
//
// So if that's the case, then let's grab the colors from the focused
// appearance as the scheme instead. We'll lose any current runtime
// changes to the color table, but those were already blown away when we
// switched to an unfocused appearance.
//
// IF WE DON'T HAVE AN UNFOCUSED APPEARANCE: then just ask the Terminal
// for it's current color table. That way, we can restore those colors
// back.
if (HasUnfocusedAppearance())
{
s.Foreground = _settings->FocusedAppearance()->DefaultForeground();
s.Background = _settings->FocusedAppearance()->DefaultBackground();
s.CursorColor = _settings->FocusedAppearance()->CursorColor();
s.Black = _settings->FocusedAppearance()->GetColorTableEntry(0);
s.Red = _settings->FocusedAppearance()->GetColorTableEntry(1);
s.Green = _settings->FocusedAppearance()->GetColorTableEntry(2);
s.Yellow = _settings->FocusedAppearance()->GetColorTableEntry(3);
s.Blue = _settings->FocusedAppearance()->GetColorTableEntry(4);
s.Purple = _settings->FocusedAppearance()->GetColorTableEntry(5);
s.Cyan = _settings->FocusedAppearance()->GetColorTableEntry(6);
s.White = _settings->FocusedAppearance()->GetColorTableEntry(7);
s.BrightBlack = _settings->FocusedAppearance()->GetColorTableEntry(8);
s.BrightRed = _settings->FocusedAppearance()->GetColorTableEntry(9);
s.BrightGreen = _settings->FocusedAppearance()->GetColorTableEntry(10);
s.BrightYellow = _settings->FocusedAppearance()->GetColorTableEntry(11);
s.BrightBlue = _settings->FocusedAppearance()->GetColorTableEntry(12);
s.BrightPurple = _settings->FocusedAppearance()->GetColorTableEntry(13);
s.BrightCyan = _settings->FocusedAppearance()->GetColorTableEntry(14);
s.BrightWhite = _settings->FocusedAppearance()->GetColorTableEntry(15);
}
else
{
s = _terminal->GetColorScheme();
}
// This might be a tad bit of a hack. This event only gets called by set
// color scheme / preview color scheme, and in that case, we know the
// control _is_ focused.
s.SelectionBackground = _settings->FocusedAppearance()->SelectionBackground();
return s;
}
// Method Description:
// - Apply the given color scheme to this control. We'll take the colors out
// of it and apply them to our focused appearance, and update the terminal
// buffer with the new color table.
// - This is here to support the Set Color Scheme action, and the ability to
// preview schemes in the control.
// Arguments:
// - scheme: the collection of colors to apply.
// Return Value:
// - <none>
void ControlCore::ColorScheme(const Core::Scheme& scheme)
{
auto l{ _terminal->LockForWriting() };
_settings->FocusedAppearance()->DefaultForeground(scheme.Foreground);
_settings->FocusedAppearance()->DefaultBackground(scheme.Background);
_settings->FocusedAppearance()->CursorColor(scheme.CursorColor);
_settings->FocusedAppearance()->SelectionBackground(scheme.SelectionBackground);
_settings->FocusedAppearance()->SetColorTableEntry(0, scheme.Black);
_settings->FocusedAppearance()->SetColorTableEntry(1, scheme.Red);
_settings->FocusedAppearance()->SetColorTableEntry(2, scheme.Green);
_settings->FocusedAppearance()->SetColorTableEntry(3, scheme.Yellow);
_settings->FocusedAppearance()->SetColorTableEntry(4, scheme.Blue);
_settings->FocusedAppearance()->SetColorTableEntry(5, scheme.Purple);
_settings->FocusedAppearance()->SetColorTableEntry(6, scheme.Cyan);
_settings->FocusedAppearance()->SetColorTableEntry(7, scheme.White);
_settings->FocusedAppearance()->SetColorTableEntry(8, scheme.BrightBlack);
_settings->FocusedAppearance()->SetColorTableEntry(9, scheme.BrightRed);
_settings->FocusedAppearance()->SetColorTableEntry(10, scheme.BrightGreen);
_settings->FocusedAppearance()->SetColorTableEntry(11, scheme.BrightYellow);
_settings->FocusedAppearance()->SetColorTableEntry(12, scheme.BrightBlue);
_settings->FocusedAppearance()->SetColorTableEntry(13, scheme.BrightPurple);
_settings->FocusedAppearance()->SetColorTableEntry(14, scheme.BrightCyan);
_settings->FocusedAppearance()->SetColorTableEntry(15, scheme.BrightWhite);
_terminal->ApplyScheme(scheme);
_renderEngine->SetSelectionBackground(til::color{ _settings->SelectionBackground() });
_renderer->TriggerRedrawAll();
_BackgroundColorChangedHandlers(*this, nullptr);
}
bool ControlCore::HasUnfocusedAppearance() const
{
return _settings->HasUnfocusedAppearance();
}
bool ControlCore::_isBackgroundTransparent()
{
// If we're:
// * Not fully opaque
// * On an acrylic background (of any opacity)
// * rendering on top of an image
//
// then the renderer should not render "default background" text with a
// fully opaque background. Doing that would cover up our nice
// transparency, or our acrylic, or our image.
return Opacity() < 1.0f || UseAcrylic() || !_settings->BackgroundImage().empty();
}
}

View File

@ -16,23 +16,35 @@
#pragma once
#include "ControlCore.g.h"
#include "ControlSettings.h"
#include "../../renderer/base/Renderer.hpp"
#include "../../cascadia/TerminalCore/Terminal.hpp"
#include "../buffer/out/search.h"
#include "cppwinrt_utils.h"
#include <til/ticket_lock.h>
namespace ControlUnitTests
{
class ControlCoreTests;
class ControlInteractivityTests;
};
#define RUNTIME_SETTING(type, name, setting) \
private: \
std::optional<type> _runtime##name{ std::nullopt }; \
void name(const type newValue) { _runtime##name = newValue; } \
\
public: \
type name() const { return til::coalesce_value(_runtime##name, setting); }
namespace winrt::Microsoft::Terminal::Control::implementation
{
struct ControlCore : ControlCoreT<ControlCore>
{
public:
ControlCore(IControlSettings settings,
ControlCore(Control::IControlSettings settings,
Control::IControlAppearance unfocusedAppearance,
TerminalConnection::ITerminalConnection connection);
~ControlCore();
@ -41,8 +53,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const double compositionScale);
void EnablePainting();
void UpdateSettings(const IControlSettings& settings);
void UpdateAppearance(const IControlAppearance& newAppearance);
void UpdateSettings(const Control::IControlSettings& settings, const IControlAppearance& newAppearance);
void ApplyAppearance(const bool& focused);
Control::IControlSettings Settings() { return *_settings; };
Control::IControlAppearance FocusedAppearance() const { return *_settings->FocusedAppearance(); };
Control::IControlAppearance UnfocusedAppearance() const { return *_settings->UnfocusedAppearance(); };
bool HasUnfocusedAppearance() const;
winrt::Microsoft::Terminal::Core::Scheme ColorScheme() const noexcept;
void ColorScheme(const winrt::Microsoft::Terminal::Core::Scheme& scheme);
void SizeChanged(const double width, const double height);
void ScaleChanged(const double scale);
uint64_t SwapChainHandle() const;
@ -57,7 +77,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
uint16_t FontWeight() const noexcept;
til::color BackgroundColor() const;
void SetBackgroundOpacity(const double opacity);
void SendInput(const winrt::hstring& wstr);
void PasteText(const winrt::hstring& hstr);
@ -148,6 +167,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
static bool IsVintageOpacityAvailable() noexcept;
RUNTIME_SETTING(double, Opacity, _settings->Opacity());
RUNTIME_SETTING(bool, UseAcrylic, _settings->UseAcrylic());
// -------------------------------- WinRT Events ---------------------------------
// clang-format off
WINRT_CALLBACK(FontSizeChanged, Control::FontSizeChangedEventArgs);
@ -178,6 +200,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
event_token _connectionOutputEventToken;
TerminalConnection::ITerminalConnection::StateChanged_revoker _connectionStateChangedRevoker;
winrt::com_ptr<ControlSettings> _settings{ nullptr };
std::unique_ptr<::Microsoft::Terminal::Core::Terminal> _terminal{ nullptr };
// NOTE: _renderEngine must be ordered before _renderer.
@ -188,8 +212,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
std::unique_ptr<::Microsoft::Console::Render::IRenderEngine> _renderEngine{ nullptr };
std::unique_ptr<::Microsoft::Console::Render::Renderer> _renderer{ nullptr };
IControlSettings _settings{ nullptr };
FontInfoDesired _desiredFont;
FontInfo _actualFont;
winrt::hstring _actualFontFaceName;
@ -249,6 +271,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void _connectionOutputHandler(const hstring& hstr);
void _updateHoveredCell(const std::optional<til::point> terminalPosition);
bool _isBackgroundTransparent();
inline bool _IsClosing() const noexcept
{
#ifndef NDEBUG

View File

@ -33,20 +33,27 @@ namespace Microsoft.Terminal.Control
[default_interface] runtimeclass ControlCore : ICoreState
{
ControlCore(IControlSettings settings,
IControlAppearance unfocusedAppearance,
Microsoft.Terminal.TerminalConnection.ITerminalConnection connection);
Boolean Initialize(Double actualWidth,
Double actualHeight,
Double compositionScale);
void UpdateSettings(IControlSettings settings);
void UpdateAppearance(IControlAppearance appearance);
void UpdateSettings(IControlSettings settings, IControlAppearance appearance);
void ApplyAppearance(Boolean focused);
IControlSettings Settings { get; };
IControlAppearance FocusedAppearance { get; };
IControlAppearance UnfocusedAppearance { get; };
Boolean HasUnfocusedAppearance();
UInt64 SwapChainHandle { get; };
Windows.Foundation.Size FontSize { get; };
String FontFaceName { get; };
UInt16 FontWeight { get; };
Double Opacity { get; };
Boolean TrySendKeyEvent(Int16 vkey,
Int16 scanCode,
@ -75,7 +82,6 @@ namespace Microsoft.Terminal.Control
void BlinkAttributeTick();
void UpdatePatternLocations();
void Search(String text, Boolean goForward, Boolean caseSensitive);
void SetBackgroundOpacity(Double opacity);
Microsoft.Terminal.Core.Color BackgroundColor { get; };
Boolean HasSelection { get; };

View File

@ -39,13 +39,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
ControlInteractivity::ControlInteractivity(IControlSettings settings,
Control::IControlAppearance unfocusedAppearance,
TerminalConnection::ITerminalConnection connection) :
_touchAnchor{ std::nullopt },
_lastMouseClickTimestamp{},
_lastMouseClickPos{},
_selectionNeedsToBeCopied{ false }
{
_core = winrt::make_self<ControlCore>(settings, connection);
_core = winrt::make_self<ControlCore>(settings, unfocusedAppearance, connection);
}
// Method Description:
@ -641,4 +642,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return _core->GetUiaData();
}
// Method Description:
// - Used by the TermControl to know if it should translate drag-dropped
// paths into WSL-friendly paths.
// Arguments:
// - <none>
// Return Value:
// - true if the connection we were created with was a WSL profile.
bool ControlInteractivity::ManglePathsForWsl()
{
return _core->Settings().ProfileSource() == L"Windows.Terminal.Wsl";
}
}

View File

@ -36,6 +36,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
public:
ControlInteractivity(IControlSettings settings,
Control::IControlAppearance unfocusedAppearance,
TerminalConnection::ITerminalConnection connection);
void GotFocus();
@ -83,6 +84,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const Windows::Foundation::IReference<CopyFormat>& formats);
void RequestPasteTextFromClipboard();
void SetEndSelectionPoint(const til::point pixelPosition);
bool ManglePathsForWsl();
TYPED_EVENT(OpenHyperlink, IInspectable, Control::OpenHyperlinkEventArgs);
TYPED_EVENT(PasteFromClipboard, IInspectable, Control::PasteFromClipboardEventArgs);

View File

@ -14,6 +14,7 @@ namespace Microsoft.Terminal.Control
[default_interface] runtimeclass ControlInteractivity
{
ControlInteractivity(IControlSettings settings,
IControlAppearance unfocusedAppearance,
Microsoft.Terminal.TerminalConnection.ITerminalConnection connection);
ControlCore Core { get; };
@ -58,6 +59,8 @@ namespace Microsoft.Terminal.Control
void UpdateScrollbar(Double newValue);
Boolean ManglePathsForWsl { get; };
event Windows.Foundation.TypedEventHandler<Object, OpenHyperlinkEventArgs> OpenHyperlink;
event Windows.Foundation.TypedEventHandler<Object, ScrollPositionChangedArgs> ScrollPositionChanged;
event Windows.Foundation.TypedEventHandler<Object, PasteFromClipboardEventArgs> PasteFromClipboard;

View File

@ -0,0 +1,81 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
--*/
#pragma once
#include "../../inc/cppwinrt_utils.h"
#include "../../inc/ControlProperties.h"
#include <DefaultSettings.h>
#include <conattrs.hpp>
#include "ControlAppearance.h"
using IFontFeatureMap = winrt::Windows::Foundation::Collections::IMap<winrt::hstring, uint32_t>;
using IFontAxesMap = winrt::Windows::Foundation::Collections::IMap<winrt::hstring, float>;
namespace winrt::Microsoft::Terminal::Control::implementation
{
struct ControlSettings : public winrt::implements<ControlSettings, Microsoft::Terminal::Control::IControlSettings, Microsoft::Terminal::Control::IControlAppearance, Microsoft::Terminal::Core::ICoreSettings, Microsoft::Terminal::Core::ICoreAppearance>
{
// Getters and setters for each *Setting member. We're not using
// WINRT_PROPERTY for these, because they actually exist inside the
// _focusedAppearance member. We don't need to reserve another member to
// hold them.
#define SETTINGS_GEN(type, name, ...) WINRT_PROPERTY(type, name, __VA_ARGS__);
CORE_SETTINGS(SETTINGS_GEN)
CONTROL_SETTINGS(SETTINGS_GEN)
#undef SETTINGS_GEN
private:
winrt::com_ptr<ControlAppearance> _unfocusedAppearance{ nullptr };
winrt::com_ptr<ControlAppearance> _focusedAppearance{ nullptr };
bool _hasUnfocusedAppearance{ false };
public:
ControlSettings(const Control::IControlSettings& settings,
const Control::IControlAppearance& unfocusedAppearance)
{
_hasUnfocusedAppearance = unfocusedAppearance != nullptr;
_focusedAppearance = winrt::make_self<implementation::ControlAppearance>(settings);
_unfocusedAppearance = unfocusedAppearance ?
winrt::make_self<implementation::ControlAppearance>(unfocusedAppearance) :
_focusedAppearance;
// Copy every value from the passed in settings, into us.
#define COPY_SETTING(type, name, ...) _##name = settings.name();
CORE_SETTINGS(COPY_SETTING)
CONTROL_SETTINGS(COPY_SETTING)
#undef COPY_SETTING
}
winrt::com_ptr<ControlAppearance> UnfocusedAppearance() { return _unfocusedAppearance; }
winrt::com_ptr<ControlAppearance> FocusedAppearance() { return _focusedAppearance; }
bool HasUnfocusedAppearance() { return _hasUnfocusedAppearance; }
// Getters and setters for each Appearance member. We're not using
// WINRT_PROPERTY for these, because they actually exist inside the
// _focusedAppearance member. We don't need to reserve another member to
// hold them.
//
// The Appearance members (including GetColorTableEntry below) are used
// when this ControlSettings is cast to a IControlAppearance or
// ICoreAppearance. In those cases, we'll always return the Focused
// appearance's version of the member. Callers who care about which
// appearance is being used should be more careful. Fortunately, this
// situation is generally only used when a control is first created, or
// when calling UpdateSettings.
#define APPEARANCE_GEN(type, name, ...) \
type name() const noexcept { return _focusedAppearance->name(); } \
void name(const type& value) noexcept { _focusedAppearance->name(value); }
CORE_APPEARANCE_SETTINGS(APPEARANCE_GEN)
CONTROL_APPEARANCE_SETTINGS(APPEARANCE_GEN)
#undef APPEARANCE_GEN
winrt::Microsoft::Terminal::Core::Color GetColorTableEntry(int32_t index) noexcept
{
return _focusedAppearance->GetColorTableEntry(index);
}
};
}

View File

@ -5,18 +5,18 @@ namespace Microsoft.Terminal.Control
{
interface IControlAppearance requires Microsoft.Terminal.Core.ICoreAppearance
{
Microsoft.Terminal.Core.Color SelectionBackground;
String BackgroundImage;
Double BackgroundImageOpacity;
Windows.UI.Xaml.Media.Stretch BackgroundImageStretchMode;
Windows.UI.Xaml.HorizontalAlignment BackgroundImageHorizontalAlignment;
Windows.UI.Xaml.VerticalAlignment BackgroundImageVerticalAlignment;
Boolean IntenseIsBold;
Microsoft.Terminal.Core.Color SelectionBackground { get; };
String BackgroundImage { get; };
Double BackgroundImageOpacity { get; };
Windows.UI.Xaml.Media.Stretch BackgroundImageStretchMode { get; };
Windows.UI.Xaml.HorizontalAlignment BackgroundImageHorizontalAlignment { get; };
Windows.UI.Xaml.VerticalAlignment BackgroundImageVerticalAlignment { get; };
Boolean IntenseIsBold { get; };
// IntenseIsBright is in Core Appearance
Double Opacity;
Double Opacity { get; };
// Experimental settings
Boolean RetroTerminalEffect;
String PixelShaderPath;
Boolean RetroTerminalEffect { get; };
String PixelShaderPath { get; };
};
}

View File

@ -24,34 +24,37 @@ namespace Microsoft.Terminal.Control
// TermControl's behavior. In these settings there is both the entirety
// of the Core ITerminalSettings interface, and any additional settings
// for specifically the control.
interface IControlSettings requires Microsoft.Terminal.Core.ICoreSettings, Microsoft.Terminal.Control.IControlAppearance
interface IControlSettings requires Microsoft.Terminal.Core.ICoreSettings,
Microsoft.Terminal.Control.IControlAppearance
{
String ProfileName;
String ProfileSource;
Boolean UseAcrylic;
ScrollbarState ScrollState;
Boolean UseAtlasEngine;
String FontFace;
Int32 FontSize;
Windows.UI.Text.FontWeight FontWeight;
String Padding;
Windows.Foundation.Collections.IMap<String, UInt32> FontFeatures;
Windows.Foundation.Collections.IMap<String, Single> FontAxes;
Boolean UseAcrylic { get; };
ScrollbarState ScrollState { get; };
Microsoft.Terminal.Control.IKeyBindings KeyBindings;
Boolean UseAtlasEngine { get; };
Boolean CopyOnSelect;
Boolean FocusFollowMouse;
String FontFace { get; };
Int32 FontSize { get; };
Windows.UI.Text.FontWeight FontWeight { get; };
String Padding { get; };
Windows.Foundation.Collections.IMap<String, UInt32> FontFeatures { get; };
Windows.Foundation.Collections.IMap<String, Single> FontAxes { get; };
String Commandline;
String StartingDirectory;
String EnvironmentVariables;
Microsoft.Terminal.Control.IKeyBindings KeyBindings { get; };
TextAntialiasingMode AntialiasingMode;
Boolean CopyOnSelect { get; };
Boolean FocusFollowMouse { get; };
String Commandline { get; };
String StartingDirectory { get; };
String EnvironmentVariables { get; };
TextAntialiasingMode AntialiasingMode { get; };
// Experimental Settings
Boolean ForceFullRepaintRendering;
Boolean SoftwareRendering;
Boolean ForceFullRepaintRendering { get; };
Boolean SoftwareRendering { get; };
};
}

View File

@ -22,5 +22,7 @@ namespace Microsoft.Terminal.Control
Boolean BracketedPasteEnabled { get; };
Microsoft.Terminal.TerminalConnection.ConnectionState ConnectionState { get; };
Microsoft.Terminal.Core.Scheme ColorScheme { get; set; };
};
}

View File

@ -48,8 +48,8 @@ DEFINE_ENUM_FLAG_OPERATORS(winrt::Microsoft::Terminal::Control::MouseButtonState
namespace winrt::Microsoft::Terminal::Control::implementation
{
TermControl::TermControl(IControlSettings settings,
Control::IControlAppearance unfocusedAppearance,
TerminalConnection::ITerminalConnection connection) :
_settings{ settings },
_isInternalScrollBarUpdate{ false },
_autoScrollVelocity{ 0 },
_autoScrollingPointerPoint{ std::nullopt },
@ -61,7 +61,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
InitializeComponent();
_interactivity = winrt::make<implementation::ControlInteractivity>(settings, connection);
_interactivity = winrt::make<implementation::ControlInteractivity>(settings, unfocusedAppearance, connection);
_core = _interactivity.Core();
// These events might all be triggered by the connection, but that
@ -77,7 +77,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// These callbacks can only really be triggered by UI interactions. So
// they don't need weak refs - they can't be triggered unless we're
// alive.
_core.BackgroundColorChanged({ this, &TermControl::_BackgroundColorChangedHandler });
_core.BackgroundColorChanged({ this, &TermControl::_coreBackgroundColorChanged });
_core.FontSizeChanged({ this, &TermControl::_coreFontSizeChanged });
_core.TransparencyChanged({ this, &TermControl::_coreTransparencyChanged });
_core.RaiseNotice({ this, &TermControl::_coreRaisedNotice });
@ -144,7 +144,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_autoScrollTimer.Interval(AutoScrollUpdateInterval);
_autoScrollTimer.Tick({ this, &TermControl::_UpdateAutoScroll });
_ApplyUISettings(_settings);
_ApplyUISettings();
}
// Method Description:
@ -229,11 +229,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
this->Focus(FocusState::Programmatic);
}
winrt::fire_and_forget TermControl::UpdateControlSettings(IControlSettings settings)
{
return UpdateControlSettings(settings, _core.UnfocusedAppearance());
}
// Method Description:
// - Given Settings having been updated, applies the settings to the current terminal.
// Return Value:
// - <none>
winrt::fire_and_forget TermControl::UpdateSettings()
winrt::fire_and_forget TermControl::UpdateControlSettings(IControlSettings settings, IControlAppearance unfocusedAppearance)
{
auto weakThis{ get_weak() };
@ -241,21 +245,18 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// terminal.
co_await winrt::resume_foreground(Dispatcher());
_UpdateSettingsFromUIThread(_settings);
_core.UpdateSettings(settings, unfocusedAppearance);
auto appearance = _settings.try_as<IControlAppearance>();
if (!_focused && _UnfocusedAppearance)
{
appearance = _UnfocusedAppearance;
}
_UpdateAppearanceFromUIThread(appearance);
_UpdateSettingsFromUIThread();
_UpdateAppearanceFromUIThread(_focused ? _core.FocusedAppearance() : _core.UnfocusedAppearance());
}
// Method Description:
// - Dispatches a call to the UI thread and updates the appearance
// Arguments:
// - newAppearance: the new appearance to set
winrt::fire_and_forget TermControl::UpdateAppearance(const IControlAppearance newAppearance)
winrt::fire_and_forget TermControl::UpdateAppearance(IControlAppearance newAppearance)
{
// Dispatch a call to the UI thread
co_await winrt::resume_foreground(Dispatcher());
@ -271,17 +272,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - INVARIANT: This method must be called from the UI thread.
// Arguments:
// - newSettings: the new settings to set
void TermControl::_UpdateSettingsFromUIThread(IControlSettings newSettings)
void TermControl::_UpdateSettingsFromUIThread()
{
if (_IsClosing())
{
return;
}
_core.UpdateSettings(_settings);
// Update our control settings
_ApplyUISettings(_settings);
_ApplyUISettings();
}
// Method Description:
@ -289,7 +288,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - INVARIANT: This method must be called from the UI thread.
// Arguments:
// - newAppearance: the new appearance to set
void TermControl::_UpdateAppearanceFromUIThread(IControlAppearance newAppearance)
void TermControl::_UpdateAppearanceFromUIThread(Control::IControlAppearance newAppearance)
{
if (_IsClosing())
{
@ -300,6 +299,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Update our control settings
const auto bg = newAppearance.DefaultBackground();
// In the future, this might need to be changed to a
// _InitializeBackgroundBrush call instead, because we may need to
// switch from a solid color brush to an acrylic one.
_changeBackgroundColor(bg);
// Set TSF Foreground
@ -307,7 +310,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
foregroundBrush.Color(static_cast<til::color>(newAppearance.DefaultForeground()));
TSFInputControl().Foreground(foregroundBrush);
_core.UpdateAppearance(newAppearance);
_core.ApplyAppearance(_focused);
}
// Method Description:
@ -331,7 +334,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
// Method Description:
// - Style our UI elements based on the values in our _settings, and set up
// - Style our UI elements based on the values in our settings, and set up
// other control-specific settings. This method will be called whenever
// the settings are reloaded.
// * Calls _InitializeBackgroundBrush to set up the Xaml brush responsible
@ -342,21 +345,21 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - <none>
// Return Value:
// - <none>
void TermControl::_ApplyUISettings(const IControlSettings& newSettings)
void TermControl::_ApplyUISettings()
{
_InitializeBackgroundBrush();
const auto bg = newSettings.DefaultBackground();
_changeBackgroundColor(bg);
// settings might be out-of-proc in the future
auto settings{ _core.Settings() };
// Apply padding as swapChainPanel's margin
const auto newMargin = ParseThicknessFromPadding(newSettings.Padding());
const auto newMargin = ParseThicknessFromPadding(settings.Padding());
SwapChainPanel().Margin(newMargin);
TSFInputControl().Margin(newMargin);
// Apply settings for scrollbar
if (newSettings.ScrollState() == ScrollbarState::Hidden)
if (settings.ScrollState() == ScrollbarState::Hidden)
{
// In the scenario where the user has turned off the OS setting to automatically hide scrollbars, the
// Terminal scrollbar would still be visible; so, we need to set the control's visibility accordingly to
@ -440,16 +443,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// use bgcolor as acrylic's tint
// - Avoids image flickering and acrylic brush redraw if settings are changed
// but the appropriate brush is still in place.
// - Does not apply background color outside of acrylic mode;
// _BackgroundColorChanged must be called to do so.
// Arguments:
// - <none>
// Return Value:
// - <none>
void TermControl::_InitializeBackgroundBrush()
{
auto appearance = _settings.try_as<IControlAppearance>();
if (_settings.UseAcrylic())
auto settings{ _core.Settings() };
auto bgColor = til::color{ _core.FocusedAppearance().DefaultBackground() }.with_alpha(0xff);
if (settings.UseAcrylic())
{
// See if we've already got an acrylic background brush
// to avoid the flicker when setting up a new one
@ -464,65 +466,83 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// see GH#1082: Initialize background color so we don't get a
// fade/flash when _BackgroundColorChanged is called
auto bgColor = til::color{ _settings.DefaultBackground() }.with_alpha(0xff);
acrylic.FallbackColor(bgColor);
acrylic.TintColor(bgColor);
// Apply brush settings
acrylic.TintOpacity(appearance.Opacity());
acrylic.TintOpacity(_core.Opacity());
// Apply brush to control if it's not already there
if (RootGrid().Background() != acrylic)
{
RootGrid().Background(acrylic);
}
// GH#5098: Inform the engine of the new opacity of the default text background.
_core.SetBackgroundOpacity(appearance.Opacity());
}
else
{
Media::SolidColorBrush solidColor{};
solidColor.Opacity(_settings.Opacity());
RootGrid().Background(solidColor);
solidColor.Opacity(_core.Opacity());
solidColor.Color(bgColor);
// GH#5098: Inform the engine of the new opacity of the default text background.
_core.SetBackgroundOpacity(appearance.Opacity());
RootGrid().Background(solidColor);
}
}
// Method Description:
// - Style the background of the control with the provided background color
// - Handler for the core's BackgroundColorChanged event. Updates the color
// of our background brush to match.
// - Hops over to the UI thread to do this work.
// Arguments:
// - color: The background color to use as a uint32 (aka DWORD COLORREF)
// <unused>
// Return Value:
// - <none>
void TermControl::_BackgroundColorChangedHandler(const IInspectable& /*sender*/,
const IInspectable& /*args*/)
{
til::color newBgColor{ _core.BackgroundColor() };
_changeBackgroundColor(newBgColor);
}
winrt::fire_and_forget TermControl::_changeBackgroundColor(const til::color bg)
winrt::fire_and_forget TermControl::_coreBackgroundColorChanged(const IInspectable& /*sender*/,
const IInspectable& /*args*/)
{
auto weakThis{ get_weak() };
co_await winrt::resume_foreground(Dispatcher());
if (auto control{ weakThis.get() })
{
if (auto acrylic = RootGrid().Background().try_as<Media::AcrylicBrush>())
{
acrylic.FallbackColor(bg);
acrylic.TintColor(bg);
}
else if (auto solidColor = RootGrid().Background().try_as<Media::SolidColorBrush>())
{
const auto originalOpacity = solidColor.Opacity();
solidColor.Color(bg);
solidColor.Opacity(originalOpacity);
}
til::color newBgColor{ _core.BackgroundColor() };
_changeBackgroundColor(newBgColor);
}
}
// Method Description:
// - Update the color of the background brush we're using. This does _not_
// update the opacity, or what type of brush it is.
// - INVARIANT: This needs to be called on the UI thread.
// Arguments:
// - bg: the new color to use as the background color.
void TermControl::_changeBackgroundColor(const til::color bg)
{
if (auto acrylic = RootGrid().Background().try_as<Media::AcrylicBrush>())
{
acrylic.FallbackColor(bg);
acrylic.TintColor(bg);
}
else if (auto solidColor = RootGrid().Background().try_as<Media::SolidColorBrush>())
{
const auto originalOpacity = solidColor.Opacity();
solidColor.Color(bg);
solidColor.Opacity(originalOpacity);
}
}
// Method Description:
// - Update the opacity of the background brush we're using. This does _not_
// update the color, or what type of brush it is.
// - INVARIANT: This needs to be called on the UI thread.
void TermControl::_changeBackgroundOpacity()
{
const auto opacity{ _core.Opacity() };
if (auto acrylic = RootGrid().Background().try_as<Media::AcrylicBrush>())
{
acrylic.TintOpacity(opacity);
}
else if (auto solidColor = RootGrid().Background().try_as<Media::SolidColorBrush>())
{
solidColor.Opacity(opacity);
}
}
@ -618,7 +638,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
{
message = { fmt::format(std::wstring_view{ RS_(L"PixelShaderNotFound") },
_settings.PixelShaderPath()) };
(_focused ? _core.FocusedAppearance() : _core.UnfocusedAppearance()).PixelShaderPath()) };
}
else if (D2DERR_SHADER_COMPILE_FAILED == hr)
{
@ -740,7 +760,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
// Now that the renderer is set up, update the appearance for initialization
_UpdateAppearanceFromUIThread(_settings);
_UpdateAppearanceFromUIThread(_core.FocusedAppearance());
_initializedTerminal = true;
@ -812,7 +832,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// This is required as part of GH#638.
// Or do so for alt+space; only send to terminal when explicitly unbound
// That is part of #GH7125
auto bindings{ _settings.KeyBindings() };
auto bindings{ _core.Settings().KeyBindings() };
bool isUnbound = false;
const KeyChord kc = {
modifiers.IsCtrlPressed(),
@ -957,7 +977,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - modifiers: The ControlKeyStates representing the modifier key states.
bool TermControl::_TryHandleKeyBinding(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers) const
{
auto bindings = _settings.KeyBindings();
// TODO: GH#5000
// The Core owning the keybindings is weird. That's for sure. In the
// future, we may want to pass the keybindings into the control
// separately, so the control can have a pointer to an in-proc
// Keybindings object, rather than routing through the ControlCore.
// (see GH#5000)
auto bindings = _core.Settings().KeyBindings();
if (!bindings)
{
return false;
@ -1136,7 +1162,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto pixelPosition = _toTerminalOrigin(cursorPosition);
const auto type = ptr.PointerDeviceType();
if (!_focused && _settings.FocusFollowMouse())
if (!_focused && _core.Settings().FocusFollowMouse())
{
_FocusFollowMouseRequestedHandlers(*this, nullptr);
}
@ -1304,7 +1330,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - Called in response to the core's TransparencyChanged event. We'll use
// this to update our background brush.
// - The Core should have already updated the TintOpacity and UseAcrylic
// properties in the _settings.
// properties in the _settings->
// Arguments:
// - <unused>
// Return Value:
@ -1315,9 +1341,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
co_await resume_foreground(Dispatcher());
try
{
_InitializeBackgroundBrush();
const auto bg = _settings.DefaultBackground();
_changeBackgroundColor(bg);
_changeBackgroundOpacity();
}
CATCH_LOG();
}
@ -1524,12 +1548,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_blinkTimer->Start();
}
// Only update the appearance here if an unfocused config exists -
// if an unfocused config does not exist then we never would have switched
// appearances anyway so there's no need to switch back upon gaining focus
if (_UnfocusedAppearance)
// Only update the appearance here if an unfocused config exists - if an
// unfocused config does not exist then we never would have switched
// appearances anyway so there's no need to switch back upon gaining
// focus
if (_core.HasUnfocusedAppearance())
{
UpdateAppearance(_settings);
UpdateAppearance(_core.FocusedAppearance());
}
}
@ -1571,9 +1596,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Check if there is an unfocused config we should set the appearance to
// upon losing focus
if (_UnfocusedAppearance)
if (_core.HasUnfocusedAppearance())
{
UpdateAppearance(_UnfocusedAppearance);
UpdateAppearance(_core.UnfocusedAppearance());
}
}
@ -1722,7 +1747,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
hstring TermControl::GetProfileName() const
{
return _settings.ProfileName();
return _core.Settings().ProfileName();
}
hstring TermControl::WorkingDirectory() const
@ -1944,7 +1969,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
double width = fontSize.Width;
double height = fontSize.Height;
// Reserve additional space if scrollbar is intended to be visible
if (_settings.ScrollState() == ScrollbarState::Visible)
if (_core.Settings().ScrollState() == ScrollbarState::Visible)
{
width += ScrollBar().ActualWidth();
}
@ -1965,7 +1990,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const winrt::Windows::Foundation::Size minSize{ 1, 1 };
const double scaleFactor = DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel();
const auto dpi = ::base::saturated_cast<uint32_t>(USER_DEFAULT_SCREEN_DPI * scaleFactor);
return GetProposedDimensions(_settings, dpi, minSize);
return GetProposedDimensions(_core.Settings(), dpi, minSize);
}
}
@ -1987,7 +2013,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
padding.Left + padding.Right :
padding.Top + padding.Bottom);
if (widthOrHeight && _settings.ScrollState() == ScrollbarState::Visible)
if (widthOrHeight && _core.Settings().ScrollState() == ScrollbarState::Visible)
{
nonTerminalArea += gsl::narrow_cast<float>(ScrollBar().ActualWidth());
}
@ -2270,7 +2296,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
std::wstring fullPath{ item.Path() };
// Fix path for WSL
if (_settings.ProfileSource() == L"Windows.Terminal.Wsl")
// In the fullness of time, we should likely plumb this up
// to the TerminalApp layer, and have it make the decision
// if this control should have it's path mangled (and do the
// mangling), rather than exposing the source concept to the
// Control layer.
//
// However, it's likely that the control layer may need to
// know about the source anyways in the future, to support
// GH#3158
if (_interactivity.ManglePathsForWsl())
{
std::replace(fullPath.begin(), fullPath.end(), L'\\', L'/');
@ -2417,12 +2452,19 @@ namespace winrt::Microsoft::Terminal::Control::implementation
IControlSettings TermControl::Settings() const
{
return _settings;
}
void TermControl::Settings(IControlSettings newSettings)
{
_settings = newSettings;
// TODO: GH#5000
// We still need this in a couple places:
// - Pane.cpp uses this for parsing out the StartingTitle, Commandline,
// etc for Pane::GetTerminalArgsForPane.
// - TerminalTab::_CreateToolTipTitle uses the ProfileName for the
// tooltip for the tab.
//
// These both happen on the UI thread right now. In the future, when we
// have to hop across the process boundary to get at the core settings,
// it may make sense to cache these values inside the TermControl
// itself, so it can do the hop once when it's first setup, rather than
// when it's needed by the UI thread.
return _core.Settings();
}
Windows::Foundation::IReference<winrt::Windows::UI::Color> TermControl::TabColor() noexcept
@ -2645,4 +2687,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
return _core.ReadEntireBuffer();
}
Core::Scheme TermControl::ColorScheme() const noexcept
{
return _core.ColorScheme();
}
void TermControl::ColorScheme(const Core::Scheme& scheme) const noexcept
{
_core.ColorScheme(scheme);
}
}

View File

@ -25,10 +25,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
struct TermControl : TermControlT<TermControl>
{
TermControl(IControlSettings settings, TerminalConnection::ITerminalConnection connection);
TermControl(IControlSettings settings,
Control::IControlAppearance unfocusedAppearance,
TerminalConnection::ITerminalConnection connection);
winrt::fire_and_forget UpdateSettings();
winrt::fire_and_forget UpdateAppearance(const IControlAppearance newAppearance);
winrt::fire_and_forget UpdateControlSettings(Control::IControlSettings settings);
winrt::fire_and_forget UpdateControlSettings(Control::IControlSettings settings, Control::IControlAppearance unfocusedAppearance);
IControlSettings Settings() const;
hstring GetProfileName() const;
@ -88,9 +91,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
Windows::UI::Xaml::Automation::Peers::AutomationPeer OnCreateAutomationPeer();
const Windows::UI::Xaml::Thickness GetPadding();
IControlSettings Settings() const;
void Settings(IControlSettings newSettings);
static Windows::Foundation::Size GetProposedDimensions(IControlSettings const& settings, const uint32_t dpi);
static Windows::Foundation::Size GetProposedDimensions(IControlSettings const& settings, const uint32_t dpi, const winrt::Windows::Foundation::Size& initialSizeInChars);
@ -105,6 +105,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
hstring ReadEntireBuffer() const;
winrt::Microsoft::Terminal::Core::Scheme ColorScheme() const noexcept;
void ColorScheme(const winrt::Microsoft::Terminal::Core::Scheme& scheme) const noexcept;
// -------------------------------- WinRT Events ---------------------------------
// clang-format off
WINRT_CALLBACK(FontSizeChanged, Control::FontSizeChangedEventArgs);
@ -127,8 +130,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
TYPED_EVENT(WarningBell, IInspectable, IInspectable);
// clang-format on
WINRT_PROPERTY(IControlAppearance, UnfocusedAppearance);
private:
friend struct TermControlT<TermControl>; // friend our parent so it can bind private event handlers
@ -146,7 +147,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
winrt::com_ptr<SearchBoxControl> _searchBox;
IControlSettings _settings;
bool _closing{ false };
bool _focused{ false };
bool _initializedTerminal{ false };
@ -193,14 +193,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return _closing;
}
void _UpdateSettingsFromUIThread(IControlSettings newSettings);
void _UpdateAppearanceFromUIThread(IControlAppearance newAppearance);
void _ApplyUISettings(const IControlSettings&);
void _UpdateSettingsFromUIThread();
void _UpdateAppearanceFromUIThread(Control::IControlAppearance newAppearance);
void _ApplyUISettings();
winrt::fire_and_forget UpdateAppearance(Control::IControlAppearance newAppearance);
void _SetBackgroundImage(const IControlAppearance& newAppearance);
void _InitializeBackgroundBrush();
void _BackgroundColorChangedHandler(const IInspectable& sender, const IInspectable& args);
winrt::fire_and_forget _changeBackgroundColor(const til::color bg);
winrt::fire_and_forget _coreBackgroundColorChanged(const IInspectable& sender, const IInspectable& args);
void _changeBackgroundColor(const til::color bg);
void _changeBackgroundOpacity();
bool _InitializeTerminal();
void _SetFontSize(int fontSize);

View File

@ -17,14 +17,15 @@ namespace Microsoft.Terminal.Control
ICoreState
{
TermControl(IControlSettings settings,
IControlAppearance unfocusedAppearance,
Microsoft.Terminal.TerminalConnection.ITerminalConnection connection);
static Windows.Foundation.Size GetProposedDimensions(IControlSettings settings, UInt32 dpi);
void UpdateSettings();
void UpdateControlSettings(IControlSettings settings);
void UpdateControlSettings(IControlSettings settings, IControlAppearance unfocusedAppearance);
Microsoft.Terminal.Control.IControlSettings Settings;
Microsoft.Terminal.Control.IControlAppearance UnfocusedAppearance;
Microsoft.Terminal.Control.IControlSettings Settings { get; };
event FontSizeChangedEventArgs FontSizeChanged;
event Windows.Foundation.TypedEventHandler<Object, TitleChangedEventArgs> TitleChanged;

View File

@ -50,6 +50,37 @@ namespace Microsoft.Terminal.Core
UInt32 Value;
};
struct Scheme
{
Microsoft.Terminal.Core.Color Foreground;
Microsoft.Terminal.Core.Color Background;
Microsoft.Terminal.Core.Color SelectionBackground;
Microsoft.Terminal.Core.Color CursorColor;
// Table: A WinRT struct doesn't allow pointers (READ: doesn't allow
// array members) in structs, but we very much would like this object to
// be a struct. So we'll call out each color individually. There's only
// 16, it's not that bad.
Microsoft.Terminal.Core.Color Black;
Microsoft.Terminal.Core.Color Red;
Microsoft.Terminal.Core.Color Green;
Microsoft.Terminal.Core.Color Yellow;
Microsoft.Terminal.Core.Color Blue;
Microsoft.Terminal.Core.Color Purple;
Microsoft.Terminal.Core.Color Cyan;
Microsoft.Terminal.Core.Color White;
Microsoft.Terminal.Core.Color BrightBlack;
Microsoft.Terminal.Core.Color BrightRed;
Microsoft.Terminal.Core.Color BrightGreen;
Microsoft.Terminal.Core.Color BrightYellow;
Microsoft.Terminal.Core.Color BrightBlue;
Microsoft.Terminal.Core.Color BrightPurple;
Microsoft.Terminal.Core.Color BrightCyan;
Microsoft.Terminal.Core.Color BrightWhite;
};
declare
{
// Forward declare this parameterized specialization so that it lives

View File

@ -170,13 +170,14 @@ void Terminal::UpdateSettings(ICoreSettings settings)
// - appearance: an ICoreAppearance with new settings values for us to use.
void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
{
_intenseIsBright = appearance.IntenseIsBright();
_adjustIndistinguishableColors = appearance.AdjustIndistinguishableColors();
// Set the default background as transparent to prevent the
// DX layer from overwriting the background image or acrylic effect
til::color newBackgroundColor{ appearance.DefaultBackground() };
_defaultBg = newBackgroundColor.with_alpha(0);
_defaultFg = appearance.DefaultForeground();
_intenseIsBright = appearance.IntenseIsBright();
_adjustIndistinguishableColors = appearance.AdjustIndistinguishableColors();
for (int i = 0; i < 16; i++)
{
@ -1290,3 +1291,67 @@ const size_t Microsoft::Terminal::Core::Terminal::GetTaskbarProgress() const noe
{
return _taskbarProgress;
}
Scheme Terminal::GetColorScheme() const noexcept
{
Scheme s;
s.Foreground = til::color{ _defaultFg };
// Don't leak the implementation detail that our _defaultBg is stored
// internally without alpha.
s.Background = til::color{ _defaultBg.with_alpha(0xff) };
// SelectionBackground is stored in the ControlAppearance
s.CursorColor = til::color{ _buffer->GetCursor().GetColor() };
s.Black = til::color{ _colorTable[0] };
s.Red = til::color{ _colorTable[1] };
s.Green = til::color{ _colorTable[2] };
s.Yellow = til::color{ _colorTable[3] };
s.Blue = til::color{ _colorTable[4] };
s.Purple = til::color{ _colorTable[5] };
s.Cyan = til::color{ _colorTable[6] };
s.White = til::color{ _colorTable[7] };
s.BrightBlack = til::color{ _colorTable[8] };
s.BrightRed = til::color{ _colorTable[9] };
s.BrightGreen = til::color{ _colorTable[10] };
s.BrightYellow = til::color{ _colorTable[11] };
s.BrightBlue = til::color{ _colorTable[12] };
s.BrightPurple = til::color{ _colorTable[13] };
s.BrightCyan = til::color{ _colorTable[14] };
s.BrightWhite = til::color{ _colorTable[15] };
return s;
}
void Terminal::ApplyScheme(const Scheme& colorScheme)
{
_defaultFg = colorScheme.Foreground;
// Set the default background as transparent to prevent the
// DX layer from overwriting the background image or acrylic effect
til::color newBackgroundColor{ colorScheme.Background };
_defaultBg = newBackgroundColor.with_alpha(0);
_colorTable[0] = til::color{ colorScheme.Black };
_colorTable[1] = til::color{ colorScheme.Red };
_colorTable[2] = til::color{ colorScheme.Green };
_colorTable[3] = til::color{ colorScheme.Yellow };
_colorTable[4] = til::color{ colorScheme.Blue };
_colorTable[5] = til::color{ colorScheme.Purple };
_colorTable[6] = til::color{ colorScheme.Cyan };
_colorTable[7] = til::color{ colorScheme.White };
_colorTable[8] = til::color{ colorScheme.BrightBlack };
_colorTable[9] = til::color{ colorScheme.BrightRed };
_colorTable[10] = til::color{ colorScheme.BrightGreen };
_colorTable[11] = til::color{ colorScheme.BrightYellow };
_colorTable[12] = til::color{ colorScheme.BrightBlue };
_colorTable[13] = til::color{ colorScheme.BrightPurple };
_colorTable[14] = til::color{ colorScheme.BrightCyan };
_colorTable[15] = til::color{ colorScheme.BrightWhite };
_buffer->GetCursor().SetColor(til::color{ colorScheme.CursorColor });
if (_adjustIndistinguishableColors)
{
_MakeAdjustedColorArray();
}
}

View File

@ -30,6 +30,7 @@ namespace winrt::Microsoft::Terminal::Core
{
struct ICoreSettings;
struct ICoreAppearance;
struct Scheme;
}
namespace Microsoft::Terminal::Core
@ -214,6 +215,9 @@ public:
const std::optional<til::color> GetTabColor() const noexcept;
til::color GetDefaultBackground() const noexcept;
winrt::Microsoft::Terminal::Core::Scheme GetColorScheme() const noexcept;
void ApplyScheme(const winrt::Microsoft::Terminal::Core::Scheme& scheme);
Microsoft::Console::Render::BlinkingState& GetBlinkingState() const noexcept;
const size_t GetTaskbarState() const noexcept;

View File

@ -350,7 +350,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
Profiles::Profiles() :
_previewControl{ Control::TermControl(Model::TerminalSettings{}, make<PreviewConnection>()) }
_previewControl{ Control::TermControl(Model::TerminalSettings{}, nullptr, make<PreviewConnection>()) }
{
InitializeComponent();
@ -405,26 +405,23 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
_PropertyChangedHandlers(*this, PropertyChangedEventArgs{ L"CurrentScrollState" });
}
_previewControl.Settings(_State.Profile().TermSettings());
_previewControl.UpdateSettings();
_previewControl.UpdateControlSettings(_State.Profile().TermSettings());
});
// The Appearances object handles updating the values in the settings UI, but
// we still need to listen to the changes here just to update the preview control
_AppearanceViewModelChangedRevoker = _State.Profile().DefaultAppearance().PropertyChanged(winrt::auto_revoke, [=](auto&&, const PropertyChangedEventArgs& /*args*/) {
_previewControl.Settings(_State.Profile().TermSettings());
_previewControl.UpdateSettings();
_previewControl.UpdateControlSettings(_State.Profile().TermSettings());
});
// Navigate to the pivot in the provided navigation state
ProfilesPivot().SelectedIndex(static_cast<int>(_State.LastActivePivot()));
_previewControl.Settings(_State.Profile().TermSettings());
// There is a possibility that the control has not fully initialized yet,
// so wait for it to initialize before updating the settings (so we know
// that the renderer is set up)
_previewControl.Initialized([&](auto&& /*s*/, auto&& /*e*/) {
_previewControl.UpdateSettings();
_previewControl.UpdateControlSettings(_State.Profile().TermSettings());
});
}

View File

@ -147,3 +147,30 @@ void ColorScheme::SetColorTableEntry(uint8_t index, const Core::Color& value) no
THROW_HR_IF(E_INVALIDARG, index >= _table.size());
_table[index] = value;
}
winrt::Microsoft::Terminal::Core::Scheme ColorScheme::ToCoreScheme() const noexcept
{
winrt::Microsoft::Terminal::Core::Scheme coreScheme{};
coreScheme.Foreground = Foreground();
coreScheme.Background = Background();
coreScheme.CursorColor = CursorColor();
coreScheme.SelectionBackground = SelectionBackground();
coreScheme.Black = Table()[0];
coreScheme.Red = Table()[1];
coreScheme.Green = Table()[2];
coreScheme.Yellow = Table()[3];
coreScheme.Blue = Table()[4];
coreScheme.Purple = Table()[5];
coreScheme.Cyan = Table()[6];
coreScheme.White = Table()[7];
coreScheme.BrightBlack = Table()[8];
coreScheme.BrightRed = Table()[9];
coreScheme.BrightGreen = Table()[10];
coreScheme.BrightYellow = Table()[11];
coreScheme.BrightBlue = Table()[12];
coreScheme.BrightPurple = Table()[13];
coreScheme.BrightCyan = Table()[14];
coreScheme.BrightWhite = Table()[15];
return coreScheme;
}

View File

@ -47,6 +47,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
static com_ptr<ColorScheme> FromJson(const Json::Value& json);
Json::Value ToJson() const;
winrt::Microsoft::Terminal::Core::Scheme ToCoreScheme() const noexcept;
com_array<Core::Color> Table() const noexcept;
void SetColorTableEntry(uint8_t index, const Core::Color& value) noexcept;

View File

@ -19,5 +19,7 @@ namespace Microsoft.Terminal.Settings.Model
// we expose the getter as a function.
Microsoft.Terminal.Core.Color[] Table();
void SetColorTableEntry(UInt8 index, Microsoft.Terminal.Core.Color value);
Microsoft.Terminal.Core.Scheme ToCoreScheme();
}
}

View File

@ -206,59 +206,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
_Opacity = appearance.Opacity();
}
// Method Description:
// - Creates a TerminalSettingsCreateResult from a parent TerminalSettingsCreateResult
// - The returned defaultSettings inherits from the parent's defaultSettings, and the
// returned unfocusedSettings inherits from the returned defaultSettings
// - Note that the unfocused settings needs to be entirely unchanged _except_ we need to
// set its parent to the other settings object that we return. This is because the overrides
// made by the control will live in that other settings object, so we want to make
// sure the unfocused settings inherit from that.
// - Another way to think about this is that initially we have UnfocusedSettings inherit
// from DefaultSettings. This function simply adds another TerminalSettings object
// in the middle of these two, so UnfocusedSettings now inherits from the new object
// and the new object inherits from the DefaultSettings. And this new object is what
// the control can put overrides in.
// Arguments:
// - parent: the TerminalSettingsCreateResult that we create a new one from
// Return Value:
// - A TerminalSettingsCreateResult object that contains a defaultSettings that inherits
// from parent's defaultSettings, and contains an unfocusedSettings that inherits from
// its defaultSettings
Model::TerminalSettingsCreateResult TerminalSettings::CreateWithParent(const Model::TerminalSettingsCreateResult& parent)
{
THROW_HR_IF_NULL(E_INVALIDARG, parent);
auto defaultImpl{ get_self<TerminalSettings>(parent.DefaultSettings()) };
auto defaultChild = defaultImpl->CreateChild();
if (parent.UnfocusedSettings())
{
parent.UnfocusedSettings().SetParent(*defaultChild);
}
return winrt::make<TerminalSettingsCreateResult>(*defaultChild, parent.UnfocusedSettings());
}
// Method Description:
// - Sets our parent to the provided TerminalSettings
// Arguments:
// - parent: our new parent
void TerminalSettings::SetParent(const Model::TerminalSettings& parent)
{
ClearParents();
com_ptr<TerminalSettings> parentImpl;
parentImpl.copy_from(get_self<TerminalSettings>(parent));
InsertParent(parentImpl);
}
Model::TerminalSettings TerminalSettings::GetParent()
{
if (_parents.size() > 0)
{
return *_parents.at(0);
}
return nullptr;
}
// Method Description:
// - Apply Profile settings, as well as any colors from our color scheme, if we have one.
// Arguments:

View File

@ -64,12 +64,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
const Model::NewTerminalArgs& newTerminalArgs,
const Control::IKeyBindings& keybindings);
static Model::TerminalSettingsCreateResult CreateWithParent(const Model::TerminalSettingsCreateResult& parent);
Model::TerminalSettings GetParent();
void SetParent(const Model::TerminalSettings& parent);
void ApplyColorScheme(const Model::ColorScheme& scheme);
// --------------------------- Core Settings ---------------------------
@ -95,7 +89,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
INHERITABLE_SETTING(Model::TerminalSettings, uint32_t, CursorHeight, DEFAULT_CURSOR_HEIGHT);
INHERITABLE_SETTING(Model::TerminalSettings, hstring, WordDelimiters, DEFAULT_WORD_DELIMITERS);
INHERITABLE_SETTING(Model::TerminalSettings, bool, CopyOnSelect, false);
INHERITABLE_SETTING(Model::TerminalSettings, bool, InputServiceWarning, true);
INHERITABLE_SETTING(Model::TerminalSettings, bool, FocusFollowMouse, false);
INHERITABLE_SETTING(Model::TerminalSettings, bool, TrimBlockSelection, false);
INHERITABLE_SETTING(Model::TerminalSettings, bool, DetectURLs, true);

View File

@ -28,12 +28,16 @@ namespace Microsoft.Terminal.Settings.Model
static TerminalSettingsCreateResult CreateWithProfile(CascadiaSettings appSettings, Profile profile, Microsoft.Terminal.Control.IKeyBindings keybindings);
static TerminalSettingsCreateResult CreateWithNewTerminalArgs(CascadiaSettings appSettings, NewTerminalArgs newTerminalArgs, Microsoft.Terminal.Control.IKeyBindings keybindings);
static TerminalSettingsCreateResult CreateWithParent(TerminalSettingsCreateResult parent);
void SetParent(TerminalSettings parent);
TerminalSettings GetParent();
void ApplyColorScheme(ColorScheme scheme);
ColorScheme AppliedColorScheme;
// The getters for these are already defined in IControlSettings. So
// we're just adding the setters here, because TerminalApp likes to be
// able to change these at runtime (e.g. when duplicating a pane).
String Commandline { set; };
String StartingDirectory { set; };
String EnvironmentVariables { set; };
};
}

View File

@ -67,7 +67,7 @@ namespace ControlUnitTests
{
Log::Comment(L"Create ControlCore object");
auto core = winrt::make_self<Control::implementation::ControlCore>(settings, conn);
auto core = winrt::make_self<Control::implementation::ControlCore>(settings, settings, conn);
core->_inUnitTests = true;
return core;
}
@ -128,13 +128,14 @@ namespace ControlUnitTests
double expectedOpacity = 0.5;
auto opacityCallback = [&](auto&&, Control::TransparencyChangedEventArgs args) mutable {
VERIFY_ARE_EQUAL(expectedOpacity, args.Opacity());
VERIFY_ARE_EQUAL(expectedOpacity, settings->Opacity());
VERIFY_ARE_EQUAL(expectedOpacity, core->_settings.Opacity());
VERIFY_ARE_EQUAL(expectedOpacity, core->Opacity());
// The Settings object's opacity shouldn't be changed
VERIFY_ARE_EQUAL(0.5, settings->Opacity());
if (expectedOpacity < 1.0)
{
VERIFY_IS_TRUE(settings->UseAcrylic());
VERIFY_IS_TRUE(core->_settings.UseAcrylic());
VERIFY_IS_TRUE(core->_settings->UseAcrylic());
}
// GH#603: Adjusting opacity shouldn't change whether or not we
@ -142,8 +143,8 @@ namespace ControlUnitTests
auto expectedUseAcrylic = winrt::Microsoft::Terminal::Control::implementation::ControlCore::IsVintageOpacityAvailable() ? true :
(expectedOpacity < 1.0 ? true : false);
VERIFY_ARE_EQUAL(expectedUseAcrylic, settings->UseAcrylic());
VERIFY_ARE_EQUAL(expectedUseAcrylic, core->_settings.UseAcrylic());
VERIFY_ARE_EQUAL(expectedUseAcrylic, core->UseAcrylic());
VERIFY_ARE_EQUAL(true, core->_settings->UseAcrylic());
};
core->TransparencyChanged(opacityCallback);

View File

@ -71,7 +71,7 @@ namespace ControlUnitTests
TerminalConnection::ITerminalConnection conn)
{
Log::Comment(L"Create ControlInteractivity object");
auto interactivity = winrt::make_self<Control::implementation::ControlInteractivity>(settings, conn);
auto interactivity = winrt::make_self<Control::implementation::ControlInteractivity>(settings, settings, conn);
VERIFY_IS_NOT_NULL(interactivity);
auto core = interactivity->_core;
core->_inUnitTests = true;
@ -116,13 +116,14 @@ namespace ControlUnitTests
double expectedOpacity = 0.5;
auto opacityCallback = [&](auto&&, Control::TransparencyChangedEventArgs args) mutable {
VERIFY_ARE_EQUAL(expectedOpacity, args.Opacity());
VERIFY_ARE_EQUAL(expectedOpacity, settings->Opacity());
VERIFY_ARE_EQUAL(expectedOpacity, core->_settings.Opacity());
VERIFY_ARE_EQUAL(expectedOpacity, core->Opacity());
// The Settings object's opacity shouldn't be changed
VERIFY_ARE_EQUAL(0.5, settings->Opacity());
auto expectedUseAcrylic = winrt::Microsoft::Terminal::Control::implementation::ControlCore::IsVintageOpacityAvailable() ? useAcrylic :
(expectedOpacity < 1.0 ? true : false);
VERIFY_ARE_EQUAL(expectedUseAcrylic, settings->UseAcrylic());
VERIFY_ARE_EQUAL(expectedUseAcrylic, core->_settings.UseAcrylic());
VERIFY_ARE_EQUAL(useAcrylic, settings->UseAcrylic());
VERIFY_ARE_EQUAL(expectedUseAcrylic, core->UseAcrylic());
};
core->TransparencyChanged(opacityCallback);

View File

@ -35,7 +35,6 @@ namespace ControlUnitTests
WINRT_PROPERTY(uint32_t, CursorHeight, DEFAULT_CURSOR_HEIGHT);
WINRT_PROPERTY(winrt::hstring, WordDelimiters, DEFAULT_WORD_DELIMITERS);
WINRT_PROPERTY(bool, CopyOnSelect, false);
WINRT_PROPERTY(bool, InputServiceWarning, true);
WINRT_PROPERTY(bool, FocusFollowMouse, false);
WINRT_PROPERTY(winrt::Windows::Foundation::IReference<winrt::Microsoft::Terminal::Core::Color>, TabColor, nullptr);

View File

@ -0,0 +1,70 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
// --------------------------- Core Appearance ---------------------------
// All of these settings are defined in ICoreAppearance.
#define CORE_APPEARANCE_SETTINGS(X) \
X(til::color, DefaultForeground, DEFAULT_FOREGROUND) \
X(til::color, DefaultBackground, DEFAULT_BACKGROUND) \
X(til::color, CursorColor, DEFAULT_CURSOR_COLOR) \
X(winrt::Microsoft::Terminal::Core::CursorStyle, CursorShape, winrt::Microsoft::Terminal::Core::CursorStyle::Vintage) \
X(uint32_t, CursorHeight, DEFAULT_CURSOR_HEIGHT) \
X(bool, IntenseIsBright, true) \
X(bool, AdjustIndistinguishableColors, true)
// --------------------------- Control Appearance ---------------------------
// All of these settings are defined in IControlSettings.
#define CONTROL_APPEARANCE_SETTINGS(X) \
X(til::color, SelectionBackground, DEFAULT_FOREGROUND) \
X(double, Opacity, 1.0) \
X(winrt::hstring, BackgroundImage) \
X(double, BackgroundImageOpacity, 1.0) \
X(winrt::Windows::UI::Xaml::Media::Stretch, BackgroundImageStretchMode, winrt::Windows::UI::Xaml::Media::Stretch::UniformToFill) \
X(winrt::Windows::UI::Xaml::HorizontalAlignment, BackgroundImageHorizontalAlignment, winrt::Windows::UI::Xaml::HorizontalAlignment::Center) \
X(winrt::Windows::UI::Xaml::VerticalAlignment, BackgroundImageVerticalAlignment, winrt::Windows::UI::Xaml::VerticalAlignment::Center) \
X(bool, IntenseIsBold) \
X(bool, RetroTerminalEffect, false) \
X(winrt::hstring, PixelShaderPath)
// --------------------------- Core Settings ---------------------------
// All of these settings are defined in ICoreSettings.
#define CORE_SETTINGS(X) \
X(int32_t, HistorySize, DEFAULT_HISTORY_SIZE) \
X(int32_t, InitialRows, 30) \
X(int32_t, InitialCols, 80) \
X(bool, SnapOnInput, true) \
X(bool, AltGrAliasing, true) \
X(winrt::hstring, WordDelimiters, DEFAULT_WORD_DELIMITERS) \
X(bool, CopyOnSelect, false) \
X(bool, FocusFollowMouse, false) \
X(winrt::Windows::Foundation::IReference<winrt::Microsoft::Terminal::Core::Color>, TabColor, nullptr) \
X(winrt::Windows::Foundation::IReference<winrt::Microsoft::Terminal::Core::Color>, StartingTabColor, nullptr) \
X(bool, TrimBlockSelection, false) \
X(bool, DetectURLs, true)
// --------------------------- Control Settings ---------------------------
// All of these settings are defined in IControlSettings.
#define CONTROL_SETTINGS(X) \
X(winrt::hstring, ProfileName) \
X(winrt::hstring, ProfileSource) \
X(bool, UseAcrylic, false) \
X(winrt::hstring, Padding, DEFAULT_PADDING) \
X(winrt::hstring, FontFace, L"Consolas") \
X(int32_t, FontSize, DEFAULT_FONT_SIZE) \
X(winrt::Windows::UI::Text::FontWeight, FontWeight) \
X(IFontFeatureMap, FontFeatures) \
X(IFontAxesMap, FontAxes) \
X(winrt::Microsoft::Terminal::Control::IKeyBindings, KeyBindings, nullptr) \
X(winrt::hstring, Commandline) \
X(winrt::hstring, StartingDirectory) \
X(winrt::hstring, StartingTitle) \
X(bool, SuppressApplicationTitle) \
X(winrt::hstring, EnvironmentVariables) \
X(winrt::Microsoft::Terminal::Control::ScrollbarState, ScrollState, winrt::Microsoft::Terminal::Control::ScrollbarState::Visible) \
X(winrt::Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, winrt::Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale) \
X(bool, ForceFullRepaintRendering, false) \
X(bool, SoftwareRendering, false) \
X(bool, ForceVTInput, false) \
X(bool, UseAtlasEngine, false)

View File

@ -324,9 +324,9 @@ void AtlasEngine::SetCallback(std::function<void()> pfn) noexcept
_api.swapChainChangedCallback = std::move(pfn);
}
void AtlasEngine::SetDefaultTextBackgroundOpacity(const float opacity) noexcept
void AtlasEngine::EnableTransparentBackground(const bool isTransparent) noexcept
{
const auto mixin = opacity == 1.0f ? 0xff000000 : 0x00000000;
const auto mixin = !isTransparent ? 0xff000000 : 0x00000000;
if (_api.backgroundOpaqueMixin != mixin)
{
_api.backgroundOpaqueMixin = mixin;

View File

@ -64,7 +64,7 @@ namespace Microsoft::Console::Render
// DxRenderer - setter
void SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE antialiasingMode) noexcept override;
void SetCallback(std::function<void()> pfn) noexcept override;
void SetDefaultTextBackgroundOpacity(float opacity) noexcept override;
void EnableTransparentBackground(const bool isTransparent) noexcept override;
void SetForceFullRepaintRendering(bool enable) noexcept override;
[[nodiscard]] HRESULT SetHwnd(HWND hwnd) noexcept override;
void SetPixelShaderPath(std::wstring_view value) noexcept override;

View File

@ -88,7 +88,7 @@ DxEngine::DxEngine() :
_forceFullRepaintRendering{ false },
_softwareRendering{ false },
_antialiasingMode{ D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE },
_defaultTextBackgroundOpacity{ 1.0f },
_defaultBackgroundIsTransparent{ true },
_hwndTarget{ static_cast<HWND>(INVALID_HANDLE_VALUE) },
_sizeTarget{},
_dpi{ USER_DEFAULT_SCREEN_DPI },
@ -911,7 +911,7 @@ void DxEngine::_ReleaseDeviceResources() noexcept
// someone has chosen the slower ClearType antialiasing (versus the faster
// grayscale antialiasing)
const bool usingCleartype = _antialiasingMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
const bool usingTransparency = _defaultTextBackgroundOpacity != 1.0f;
const bool usingTransparency = _defaultBackgroundIsTransparent;
// Another way of naming "bgIsDefault" is "bgHasTransparency"
const auto bgIsDefault = (_backgroundColor.a == _defaultBackgroundColor.a) &&
(_backgroundColor.r == _defaultBackgroundColor.r) &&
@ -1927,20 +1927,16 @@ CATCH_RETURN()
const bool /*usingSoftFont*/,
const bool isSettingDefaultBrushes) noexcept
{
// GH#5098: If we're rendering with cleartype text, we need to always render
// onto an opaque background. If our background's opacity is 1.0f, that's
// great, we can actually use cleartype in that case. In that scenario
// (cleartype && opacity == 1.0), we'll force the opacity bits of the
// COLORREF to 0xff so we draw as cleartype. In any other case, leave the
// opacity bits unchanged. PaintBufferLine will later do some logic to
// determine if we should paint the text as grayscale or not.
const bool usingCleartype = _antialiasingMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
const bool usingTransparency = _defaultTextBackgroundOpacity != 1.0f;
const bool forceOpaqueBG = usingCleartype && !usingTransparency;
const auto [colorForeground, colorBackground] = pData->GetAttributeColors(textAttributes);
const bool usingCleartype = _antialiasingMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
const bool usingTransparency = _defaultBackgroundIsTransparent;
const bool forceOpaqueBG = usingCleartype && !usingTransparency;
_foregroundColor = _ColorFFromColorRef(OPACITY_OPAQUE | colorForeground);
// October 2021: small changes were made to the way BG color interacts with
// grayscale AA, esp. with regards to acrylic and GH#5098. See comment in
// _ShouldForceGrayscaleAA for more details.
_backgroundColor = _ColorFFromColorRef((forceOpaqueBG ? OPACITY_OPAQUE : 0) | colorBackground);
_d2dBrushForeground->SetColor(_foregroundColor);
@ -2237,14 +2233,19 @@ CATCH_LOG()
// rendering onto a transparent surface (like acrylic), then cleartype won't
// work correctly, and will actually just additively blend with the
// background. This is here to support GH#5098.
// - We'll use this, along with whether cleartype was requested, to manually set
// the alpha channel of the background brush to 1.0. We need to do that to
// make cleartype work without blending. However, we don't want to do that too
// often - if we do that on top of a transparent BG, then the entire swap
// chain will be fully opaque.
// Arguments:
// - opacity: the new opacity of our background, on [0.0f, 1.0f]
// - isTransparent: true if our BG is transparent (acrylic, or anything that's not fully opaque)
// Return Value:
// - <none>
void DxEngine::SetDefaultTextBackgroundOpacity(const float opacity) noexcept
void DxEngine::EnableTransparentBackground(const bool isTransparent) noexcept
try
{
_defaultTextBackgroundOpacity = opacity;
_defaultBackgroundIsTransparent = isTransparent;
// Make sure we redraw all the cells, to update whether they're actually
// drawn with cleartype or not.

View File

@ -128,7 +128,7 @@ namespace Microsoft::Console::Render
void SetSelectionBackground(const COLORREF color, const float alpha = 0.5f) noexcept override;
void SetAntialiasingMode(const D2D1_TEXT_ANTIALIAS_MODE antialiasingMode) noexcept override;
void SetDefaultTextBackgroundOpacity(const float opacity) noexcept override;
void EnableTransparentBackground(const bool isTransparent) noexcept override;
void SetIntenseIsBold(const bool opacity) noexcept override;
void UpdateHyperlinkHoveredId(const uint16_t hoveredId) noexcept override;
@ -257,7 +257,7 @@ namespace Microsoft::Console::Render
D2D1_TEXT_ANTIALIAS_MODE _antialiasingMode;
float _defaultTextBackgroundOpacity;
bool _defaultBackgroundIsTransparent;
bool _intenseIsBold;
// DirectX constant buffers need to be a multiple of 16; align to pad the size.

View File

@ -104,7 +104,7 @@ namespace Microsoft::Console::Render
// DxRenderer - setter
virtual void SetAntialiasingMode(const D2D1_TEXT_ANTIALIAS_MODE antialiasingMode) noexcept {}
virtual void SetCallback(std::function<void()> pfn) noexcept {}
virtual void SetDefaultTextBackgroundOpacity(const float opacity) noexcept {}
virtual void EnableTransparentBackground(const bool isTransparent) noexcept {}
virtual void SetForceFullRepaintRendering(bool enable) noexcept {}
virtual [[nodiscard]] HRESULT SetHwnd(const HWND hwnd) noexcept { return E_NOTIMPL; }
virtual void SetPixelShaderPath(std::wstring_view value) noexcept {}