-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
Provide the focused tab title in the Tray Icon's context menu #11043
Conversation
@@ -35,6 +35,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation | |||
|
|||
winrt::Microsoft::Terminal::Remoting::CommandlineArgs InitialArgs(); | |||
WINRT_PROPERTY(winrt::hstring, WindowName); | |||
WINRT_PROPERTY(winrt::hstring, ActiveTabTitle); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't actually know what to call this - WindowTitle? FocusedTabTitle?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WindowTitle
might be more appropriate, since users can also suppress the "use tab title as window title" behavior (and then the window's title is just Windows Terminal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one I actually prefer not to be the window title. Imagine, you'd have a list inside of a Terminal tray icon that just says "Windows Terminal, Windows Terminal, Windows Terminal, Windows Terminal, Windows Terminal". Then again, that's my bias. 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea that's a good point. Plus, I hadn't read to AppHost.cpp:311
yet when I made this comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright so I don't love the idea of returning the Peasants out of the Monarch. I just worry that's a potential footgun if people aren't careful.
That being said, we need to return something with multiple values here. We may need to do something like
struct PeasantInfo{
UInt64 Id;
String Name;
String TabTitle;
}
...
[default_interface] runtimeclass Monarch {
...
Windows.Foundation.Collections.IMapView<UInt64, PeasantInfo> GetPeasantInfo { get; };
...
}
If we do it like that, then I think WinRT will marshal the entire PeasantInfo
struct into the calling process, rather than pass a com_ptr to the object residing in (some other process).
HMU on teams if that sounds insane. Also @DHowett call me out if that's not how winrt works
@@ -35,6 +35,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation | |||
|
|||
winrt::Microsoft::Terminal::Remoting::CommandlineArgs InitialArgs(); | |||
WINRT_PROPERTY(winrt::hstring, WindowName); | |||
WINRT_PROPERTY(winrt::hstring, ActiveTabTitle); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WindowTitle
might be more appropriate, since users can also suppress the "use tab title as window title" behavior (and then the window's title is just Windows Terminal
if (_logic.GetShowTitleInTitlebar()) | ||
{ | ||
_window->UpdateTitle(newTitle); | ||
} | ||
_windowManager.UpdateTitle(newTitle); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah okay. I see. You changed the title handling so that we always bubble the focused tab title up. So maybe it should be ActiveTabTitle
, not WindowTitle
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dig it, thanks for bearing with me
src/cascadia/Remoting/Monarch.cpp
Outdated
// Remove the dead peasants we came across while iterating. | ||
for (const auto& id : peasantsToErase) | ||
{ | ||
_peasants.erase(id); | ||
_clearOldMruEntries(id); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the time is nigh to abstract this away, as it's been repeated 3x now in this file.
You can put something like this into the header:
template<typename F>
void _forEachPeasant(F&& func)
{
using Map = decltype(_peasants);
using R = std::invoke_result_t<F, Map::key_type, Map::mapped_type>;
static constexpr auto IsVoid = std::is_void_v<R>;
std::vector<uint64_t> peasantsToErase;
for (const auto& [id, p] : _peasants)
{
try
{
if constexpr (IsVoid)
{
func(id, p);
}
else
{
if (!func(id, p))
{
break;
}
}
}
catch (const winrt::hresult_error& exception)
{
if (exception.code() == 0x800706ba) // The RPC server is unavailable.
{
peasantsToErase.emplace_back(id);
}
else
{
LOG_CAUGHT_EXCEPTION();
throw;
}
}
}
for (const auto& id : peasantsToErase)
{
_peasants.erase(id);
_clearOldMruEntries(id);
}
}
Then use it like that:
Windows::Foundation::Collections::IVectorView<Remoting::PeasantInfo> Monarch::GetPeasantInfos()
{
std::vector<Remoting::PeasantInfo> names;
names.reserve(_peasants.size());
_forEachPeasant([&](const auto& id, const auto& p) {
names.emplace_back(id, p.WindowName(), p.ActiveTabTitle());
});
return winrt::single_threaded_vector(std::move(names)).GetView();
}
bool Monarch::DoesQuakeWindowExist()
{
bool result = false;
_forEachPeasant([&](const auto& id, const auto& p) {
if (p.WindowName() == QuakeWindowName)
{
result = true;
}
// In other words:
// "continue if we didn't get a positive result"
return !result;
});
return result;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe you can even replace all usages of _forAllPeasantsIgnoringTheDead
with that template.
@zadjii-msft Idk if that's correct. May _forAllPeasantsIgnoringTheDead
remove dead peasants?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May
_forAllPeasantsIgnoringTheDead
remove dead peasants?
Meh, I suppose it could. off the top of my head, I don't remember if there was a specific reason it doesn't. IIRC, for things that were using _forAllPeasantsIgnoringTheDead
, it didn't really matter if a peasant had died. I just left the removal for something later on that actually did care if the peasant had died.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated my above template to contain:
catch (const winrt::hresult_error& exception)
{
if (exception.code() == 0x800706ba) // The RPC server is unavailable.
{
peasantsToErase.emplace_back(id);
}
else
{
LOG_CAUGHT_EXCEPTION();
throw;
}
}
What do you think about that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it will replace _forAllPeasantsIgnoringTheDead
, it should probably also accept an onError
function then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can just replace _forAllPeasantsIgnoringTheDead
a different time. I don't know how important the two TraceLoggingWrite
calls are...
Although it would be preferable if _forAllPeasantsIgnoringTheDead
was a template as well so that we don't have to use std::function
(which prevents inlining).
Hello @leonMSFT! Because this pull request has the p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (
|
BTW I realized after this PR was merged that you can also write this: fmt::memory_buffer out;
fmt::format_to(out, L"#{}", p.Id);
if (!p.TabTitle.empty())
{
fmt::format_to(out, L": {}", p.TabTitle);
}
if (!p.Name.empty())
{
fmt::format_to(out, L" [{}]", p.Name);
}
fmt::format_to(out, L"\0");
AppendMenu(submenu, MF_STRING, gsl::narrow<UINT_PTR>(p.Id), out.data()); It doesn't even allocate anything on the heap! |
🎉 Handy links: |
This PR adds a bit more information to each item in the Tray Icon's window selection submenu.
Currently it only shows the window ID and window name if given one.
Now each item will instead show
{Window ID} : {Active Tab Title} [{Window Name}]