-
Notifications
You must be signed in to change notification settings - Fork 8.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Display connection state in tab and add context menu entry for restarting connection #15760
Display connection state in tab and add context menu entry for restarting connection #15760
Conversation
Drive by notes:
|
@zadjii-msft Indeed we have the same problem here. Do you have an agreed way to solve this kind of issue? Actually, I've also noticed another sort of race condition here. When you right-click on a non-active pane, it becomes active, but the context menu may be displayed before this happens (I suppose these events are asynchronous), thus showing the Restart Connection item based the wrong pane's status. Not sure how to fix it either. |
I'm literally working on that right now. I believe the code we have right now just manually tries to focus the tab that requested the action, then does the action. Something like terminal/src/cascadia/TerminalApp/TabManagement.cpp Lines 191 to 201 in d70794a
That seems... unnecessarily wacky. I'm trying to rewrite bits of the TerminalTab so we don't always have to be raising events requesting the page to then do something with the tab. I want to just be able to fire off the ActionAndArgs, bundled with the sender, and have the handlers figure out who to call it on. |
FWIW #15773 should merge after CI runs, and that should make this a little easier |
This PR's goal is to allow something like a `Tab` to raise a ShortcutAction, by saying "this action should be performed on ME". We've had a whole category of these issues in the past: * #15734 * #15760 * #13579 * #13942 * #13942 * Heck even dating back to #10832 So, this tries to remove a bit of that footgun. This probably isn't the _final_ form of what this refactor might look like, but the code is certainly better than before. Basically, there's a few bits: * `ShortcutActionDispatch.DoAction` now takes a `sender`, which can be _anything_. * Most actions that use a "Get the focused _thing_ then do something to it" are changed to "If there was a sender, let's use that - otherwise, we'll use the focused _thing_". * TerminalTab was largely refactored to use this, instead of making requests to the `TerminalPage` to just do a thing to it. I've got a few TODO!s left, but wanted to get initial feedback. * [x] `TerminalPage::_HandleTogglePaneZoom` * [x] `TerminalPage::_HandleFocusPane` * [x] `TerminalPage::_MoveTab` Closes #15734
…te_in_tab # Conflicts: # src/cascadia/TerminalApp/Resources/en-US/Resources.resw
There is still this small race condition I don't know how to fix
|
As far as I can see, when a pane is (right)clicked:
The first point is done asynchronously, so may update the active pane too late when the menu is already displayed (despite both end up in the UI thread). terminal/src/cascadia/TerminalControl/TermControl.cpp Lines 1472 to 1520 in 8daf89e
@zadjii-msft @lhecker Free to comment if you see how we could resolve this, otherwise if you feel that it would require quite a big change for this PR I can just leave it to you 😄 |
How do we feel about diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp
index f7edf6397..59ad78e23 100644
--- a/src/cascadia/TerminalApp/TerminalPage.cpp
+++ b/src/cascadia/TerminalApp/TerminalPage.cpp
@@ -1661,8 +1661,18 @@ namespace winrt::TerminalApp::implementation
term.CompletionsChanged({ get_weak(), &TerminalPage::_ControlCompletionsChangedHandler });
}
- term.ContextMenu().Opening({ this, &TerminalPage::_ContextMenuOpened });
- term.SelectionContextMenu().Opening({ this, &TerminalPage::_SelectionMenuOpened });
+ term.ContextMenu().Opening([weak = get_weak(), weakTerm = term.get_weak()](auto&& sender, auto&& args) {
+ if (const auto& page{ weak.get() })
+ {
+ _PopulateContextMenu(weakTerm.get(), sender.try_as<MUX::Controls::CommandBarFlyout>(), false);
+ }
+ });
+ term.SelectionContextMenu().Opening([weak = get_weak(), weakTerm = term.get_weak()](auto&& sender, auto&& args) {
+ if (const auto& page{ weak.get() })
+ {
+ _PopulateContextMenu(weakTerm.get(), sender.try_as<MUX::Controls::CommandBarFlyout>(), true);
+ }
+ });
}
// Method Description:
@@ -4801,25 +4811,14 @@ namespace winrt::TerminalApp::implementation
characterSize.Height);
}
- void TerminalPage::_ContextMenuOpened(const IInspectable& sender,
- const IInspectable& /*args*/)
- {
- _PopulateContextMenu(sender, false /*withSelection*/);
- }
- void TerminalPage::_SelectionMenuOpened(const IInspectable& sender,
- const IInspectable& /*args*/)
- {
- _PopulateContextMenu(sender, true /*withSelection*/);
- }
-
- void TerminalPage::_PopulateContextMenu(const IInspectable& sender,
+ void TerminalPage::_PopulateContextMenu(const TermControl& control,
+ const MUX::Controls::CommandBarFlyout& menu,
const bool withSelection)
{
// withSelection can be used to add actions that only appear if there's
// selected text, like "search the web"
- const auto& menu{ sender.try_as<MUX::Controls::CommandBarFlyout>() };
- if (!menu)
+ if (!control || !menu)
{
return;
}
@@ -4869,12 +4868,9 @@ namespace winrt::TerminalApp::implementation
makeItem(RS_(L"PaneClose"), L"\xE89F", ActionAndArgs{ ShortcutAction::ClosePane, nullptr });
}
- if (const auto pane{ _GetFocusedTabImpl()->GetActivePane() })
+ if (control.ConnectionState() >= ConnectionState::Closed)
{
- if (pane->IsConnectionClosed())
- {
- makeItem(RS_(L"RestartConnectionText"), L"\xE72C", ActionAndArgs{ ShortcutAction::RestartConnection, nullptr });
- }
+ makeItem(RS_(L"RestartConnectionText"), L"\xE72C", ActionAndArgs{ ShortcutAction::RestartConnection, nullptr });
}
if (withSelection)
diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h
index fd63f7cc6..d70d09ded 100644
--- a/src/cascadia/TerminalApp/TerminalPage.h
+++ b/src/cascadia/TerminalApp/TerminalPage.h
@@ -535,9 +535,7 @@ namespace winrt::TerminalApp::implementation
const std::optional<til::point>& dragPoint = std::nullopt);
void _sendDraggedTabToWindow(const winrt::hstring& windowId, const uint32_t tabIndex, std::optional<til::point> dragPoint);
- void _ContextMenuOpened(const IInspectable& sender, const IInspectable& args);
- void _SelectionMenuOpened(const IInspectable& sender, const IInspectable& args);
- void _PopulateContextMenu(const IInspectable& sender, const bool withSelection);
+ void _PopulateContextMenu(const Microsoft::Terminal::Control::TermControl& control, const Microsoft::UI::Xaml::Controls::CommandBarFlyout& sender, const bool withSelection);
winrt::Windows::UI::Xaml::Controls::MenuFlyout _CreateRunAsAdminFlyout(int profileIndex);
winrt::Microsoft::Terminal::Control::TermControl _senderOrActiveControl(const winrt::Windows::Foundation::IInspectable& sender); (not tested) We plumb the control that the context menu was opened for all the way through to where the event is actually handled (in |
In the interest of getting this in to cut a 1.19 build: 2450775 If you don't have time, we can just merge this as-is tomorrow morning, and add that commit in post. Whatever you feel is best |
Probably I won't be able to work on it today, feel free to go ahead in the interest of the product 💪 |
…e one (#15999) As mentioned in #15760 > > When you right-click on a non-active pane, it becomes active, but the context menu may be displayed before this happens, thus showing the Restart Connection item based the wrong pane's status. > > As far as I can see, when a pane is (right)clicked: > > 1. If unfocused, `Focus` is called. This goes through the `GotFocus` handler which eventually calls `tab->_UpdateActivePane(sender);` > 2. `PointerPressed` is raised which eventually shows the context menu > > The first point is done asynchronously, so may update the active pane too late when the menu is already displayed (despite both end up in the UI thread). To fix this: we plumb the control that the context menu was opened for all the way through to where the event is actually handled (in `_PopulateContextMenu`) * [x] Tested manually Co-authored-by: Marco Pelagatti <1140981+mpela81@users.noreply.github.com>
This PR's goal is to allow something like a `Tab` to raise a ShortcutAction, by saying "this action should be performed on ME". We've had a whole category of these issues in the past: * #15734 * #15760 * #13579 * #13942 * #13942 * Heck even dating back to #10832 So, this tries to remove a bit of that footgun. This probably isn't the _final_ form of what this refactor might look like, but the code is certainly better than before. Basically, there's a few bits: * `ShortcutActionDispatch.DoAction` now takes a `sender`, which can be _anything_. * Most actions that use a "Get the focused _thing_ then do something to it" are changed to "If there was a sender, let's use that - otherwise, we'll use the focused _thing_". * TerminalTab was largely refactored to use this, instead of making requests to the `TerminalPage` to just do a thing to it. I've got a few TODO!s left, but wanted to get initial feedback. * [x] `TerminalPage::_HandleTogglePaneZoom` * [x] `TerminalPage::_HandleFocusPane` * [x] `TerminalPage::_MoveTab` Closes #15734 (cherry picked from commit 30eb9ee) Service-Card-Id: 90438493 Service-Version: 1.18
Summary of the Pull Request
When a connection is Closed, show an indicator in the respective tab.
When the active pane's connection is Closed, show a "Restart Connection" action in the right-click context menu and in the tab context menu.
Validation Steps Performed
PR Checklist