From 47f4b4197d82f3e4cdb3886148a25f9ff30322c4 Mon Sep 17 00:00:00 2001 From: Don-Vito Date: Wed, 10 Feb 2021 00:18:20 +0200 Subject: [PATCH] Add support for "focus follows mouse" mode (#8965) ## PR Checklist * [x] Closes #6459 * [x] CLA signed. * [ ] Tests added/passed * [x] Documentation updated here: https://github.com/MicrosoftDocs/terminal/pull/248 * [x] Schema updated. * [x] I've discussed this with core contributors already. --- doc/cascadia/profiles.schema.json | 5 +++++ src/cascadia/TerminalApp/TerminalSettings.cpp | 1 + src/cascadia/TerminalApp/TerminalSettings.h | 1 + src/cascadia/TerminalControl/IControlSettings.idl | 1 + src/cascadia/TerminalControl/TermControl.cpp | 5 +++++ src/cascadia/TerminalSettingsEditor/Interaction.xaml | 5 +++++ .../TerminalSettingsEditor/Resources/en-US/Resources.resw | 6 ++++++ src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp | 5 +++++ src/cascadia/TerminalSettingsModel/GlobalAppSettings.h | 1 + src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl | 4 ++++ src/cascadia/TerminalSettingsModel/defaults.json | 1 + src/cascadia/UnitTests_TerminalCore/MockTermSettings.h | 3 +++ 12 files changed, 38 insertions(+) diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json index 417ab32e280..9a43234411a 100644 --- a/doc/cascadia/profiles.schema.json +++ b/doc/cascadia/profiles.schema.json @@ -635,6 +635,11 @@ "description": "When set to true, a selection is immediately copied to your clipboard upon creation. When set to false, the selection persists and awaits further action.", "type": "boolean" }, + "focusFollowMouse": { + "default": false, + "description": "When set to true, the terminal will focus the pane on mouse hover.", + "type": "boolean" + }, "copyFormatting": { "default": true, "description": "When set to `true`, the color and font formatting of selected text is also copied to your clipboard. When set to `false`, only plain text is copied to your clipboard. An array of specific formats can also be used. Supported array values include `html` and `rtf`. Plain text is always copied.", diff --git a/src/cascadia/TerminalApp/TerminalSettings.cpp b/src/cascadia/TerminalApp/TerminalSettings.cpp index 6d87c410ad4..2f3cb99b0aa 100644 --- a/src/cascadia/TerminalApp/TerminalSettings.cpp +++ b/src/cascadia/TerminalApp/TerminalSettings.cpp @@ -208,6 +208,7 @@ namespace winrt::TerminalApp::implementation _WordDelimiters = globalSettings.WordDelimiters(); _CopyOnSelect = globalSettings.CopyOnSelect(); + _FocusFollowMouse = globalSettings.FocusFollowMouse(); _ForceFullRepaintRendering = globalSettings.ForceFullRepaintRendering(); _SoftwareRendering = globalSettings.SoftwareRendering(); _ForceVTInput = globalSettings.ForceVTInput(); diff --git a/src/cascadia/TerminalApp/TerminalSettings.h b/src/cascadia/TerminalApp/TerminalSettings.h index 8953dc67dbb..34d83fc28ab 100644 --- a/src/cascadia/TerminalApp/TerminalSettings.h +++ b/src/cascadia/TerminalApp/TerminalSettings.h @@ -64,6 +64,7 @@ namespace winrt::TerminalApp::implementation GETSET_SETTING(uint32_t, CursorHeight, DEFAULT_CURSOR_HEIGHT); GETSET_SETTING(hstring, WordDelimiters, DEFAULT_WORD_DELIMITERS); GETSET_SETTING(bool, CopyOnSelect, false); + GETSET_SETTING(bool, FocusFollowMouse, false); GETSET_SETTING(Windows::Foundation::IReference, TabColor, nullptr); diff --git a/src/cascadia/TerminalControl/IControlSettings.idl b/src/cascadia/TerminalControl/IControlSettings.idl index cfca032ce8d..0c80d68b1e3 100644 --- a/src/cascadia/TerminalControl/IControlSettings.idl +++ b/src/cascadia/TerminalControl/IControlSettings.idl @@ -39,6 +39,7 @@ namespace Microsoft.Terminal.TerminalControl Microsoft.Terminal.TerminalControl.IKeyBindings KeyBindings; Boolean CopyOnSelect; + Boolean FocusFollowMouse; String Commandline; String StartingDirectory; diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 0761eb064b1..e46a5e8ab11 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1362,6 +1362,11 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation const auto cursorPosition = point.Position(); const auto terminalPosition = _GetTerminalPosition(cursorPosition); + if (!_focused && _settings.FocusFollowMouse()) + { + Focus(FocusState::Pointer); + } + if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Mouse || ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Pen) { if (_focused && _CanSendVTMouseInput()) diff --git a/src/cascadia/TerminalSettingsEditor/Interaction.xaml b/src/cascadia/TerminalSettingsEditor/Interaction.xaml index 3a0efbd4229..701e12a1dc4 100644 --- a/src/cascadia/TerminalSettingsEditor/Interaction.xaml +++ b/src/cascadia/TerminalSettingsEditor/Interaction.xaml @@ -54,6 +54,11 @@ the MIT License. See LICENSE in the project root for license information. --> ItemsSource="{x:Bind TabSwitcherModeList}" ItemTemplate="{StaticResource EnumRadioButtonTemplate}"/> + + + + + diff --git a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw index 9ae096c02a1..bb8ac02dc49 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw @@ -825,4 +825,10 @@ a lower layer This is the object of "SettingContainer_OverrideIntro". + + Enable Focus Follow Mouse mode + + + When checked, the terminal will the focus pane on mouse hover. + diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp index 4d2d904f878..61846613bc0 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp @@ -41,6 +41,7 @@ static constexpr std::string_view LegacyUseTabSwitcherModeKey{ "useTabSwitcher" static constexpr std::string_view TabSwitcherModeKey{ "tabSwitcherMode" }; static constexpr std::string_view DisableAnimationsKey{ "disableAnimations" }; static constexpr std::string_view StartupActionsKey{ "startupActions" }; +static constexpr std::string_view FocusFollowMouseKey{ "focusFollowMouse" }; static constexpr std::string_view DebugFeaturesKey{ "debugFeatures" }; @@ -116,6 +117,7 @@ winrt::com_ptr GlobalAppSettings::Copy() const globals->_TabSwitcherMode = _TabSwitcherMode; globals->_DisableAnimations = _DisableAnimations; globals->_StartupActions = _StartupActions; + globals->_FocusFollowMouse = _FocusFollowMouse; globals->_UnparsedDefaultProfile = _UnparsedDefaultProfile; globals->_validDefaultProfile = _validDefaultProfile; @@ -304,6 +306,8 @@ void GlobalAppSettings::LayerJson(const Json::Value& json) JsonUtils::GetValueForKey(json, StartupActionsKey, _StartupActions); + JsonUtils::GetValueForKey(json, FocusFollowMouseKey, _FocusFollowMouse); + // This is a helper lambda to get the keybindings and commands out of both // and array of objects. We'll use this twice, once on the legacy // `keybindings` key, and again on the newer `bindings` key. @@ -399,6 +403,7 @@ Json::Value GlobalAppSettings::ToJson() const JsonUtils::SetValueForKey(json, TabSwitcherModeKey, _TabSwitcherMode); JsonUtils::SetValueForKey(json, DisableAnimationsKey, _DisableAnimations); JsonUtils::SetValueForKey(json, StartupActionsKey, _StartupActions); + JsonUtils::SetValueForKey(json, FocusFollowMouseKey, _FocusFollowMouse); // clang-format on // TODO GH#8100: keymap needs to be serialized here diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h index 8e1e65942b4..bfa47d63718 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h @@ -87,6 +87,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation GETSET_SETTING(Model::TabSwitcherMode, TabSwitcherMode, Model::TabSwitcherMode::InOrder); GETSET_SETTING(bool, DisableAnimations, false); GETSET_SETTING(hstring, StartupActions, L""); + GETSET_SETTING(bool, FocusFollowMouse, false); private: guid _defaultProfile; diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl index 6f0fc41dac1..e9ffca476db 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl @@ -146,5 +146,9 @@ namespace Microsoft.Terminal.Settings.Model Boolean HasStartupActions(); void ClearStartupActions(); String StartupActions(); + + Boolean HasFocusFollowMouse(); + void ClearFocusFollowMouse(); + Boolean FocusFollowMouse; } } diff --git a/src/cascadia/TerminalSettingsModel/defaults.json b/src/cascadia/TerminalSettingsModel/defaults.json index 0986f4acd62..7c7e8329d7b 100644 --- a/src/cascadia/TerminalSettingsModel/defaults.json +++ b/src/cascadia/TerminalSettingsModel/defaults.json @@ -27,6 +27,7 @@ "snapToGridOnResize": true, "disableAnimations": false, "startupActions": "", + "focusFollowMouse": false, "profiles": [ diff --git a/src/cascadia/UnitTests_TerminalCore/MockTermSettings.h b/src/cascadia/UnitTests_TerminalCore/MockTermSettings.h index e55e17b9612..3100c7f5f60 100644 --- a/src/cascadia/UnitTests_TerminalCore/MockTermSettings.h +++ b/src/cascadia/UnitTests_TerminalCore/MockTermSettings.h @@ -35,6 +35,7 @@ namespace TerminalCoreUnitTests uint32_t CursorHeight() { return 42UL; } winrt::hstring WordDelimiters() { return winrt::hstring(DEFAULT_WORD_DELIMITERS); } bool CopyOnSelect() { return _copyOnSelect; } + bool FocusFollowMouse() { return _focusFollowMouse; } winrt::hstring StartingTitle() { return _startingTitle; } bool SuppressApplicationTitle() { return _suppressApplicationTitle; } uint32_t SelectionBackground() { return COLOR_WHITE; } @@ -56,6 +57,7 @@ namespace TerminalCoreUnitTests void CursorHeight(uint32_t) {} void WordDelimiters(winrt::hstring) {} void CopyOnSelect(bool copyOnSelect) { _copyOnSelect = copyOnSelect; } + void FocusFollowMouse(bool focusFollowMouse) { _focusFollowMouse = focusFollowMouse; } void StartingTitle(winrt::hstring const& value) { _startingTitle = value; } void SuppressApplicationTitle(bool suppressApplicationTitle) { _suppressApplicationTitle = suppressApplicationTitle; } void SelectionBackground(uint32_t) {} @@ -69,6 +71,7 @@ namespace TerminalCoreUnitTests int32_t _initialRows; int32_t _initialCols; bool _copyOnSelect{ false }; + bool _focusFollowMouse{ false }; bool _suppressApplicationTitle{ false }; winrt::hstring _startingTitle; };