Ask the TerminalApp to parse the commandline, and tell us what the window should be. It just always says 0 for now, but in the future it could actually give us useful info.

This commit is contained in:
Mike Griese 2021-01-06 07:10:54 -06:00
parent 00184e7ef6
commit 658db6b568
14 changed files with 161 additions and 2 deletions

View file

@ -0,0 +1,5 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "FindTargetWindowArgs.h"
#include "FindTargetWindowArgs.g.cpp"

View file

@ -0,0 +1,17 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "FindTargetWindowArgs.g.h"
#include "../cascadia/inc/cppwinrt_utils.h"
namespace winrt::Microsoft::Terminal::Remoting::implementation
{
struct FindTargetWindowArgs : public FindTargetWindowArgsT<FindTargetWindowArgs>
{
public:
GETSET_PROPERTY(winrt::Microsoft::Terminal::Remoting::CommandlineArgs, Args, nullptr);
GETSET_PROPERTY(int, ResultTargetWindow, -1);
};
}

View file

@ -19,6 +19,9 @@
<ClInclude Include="Monarch.h">
<DependentUpon>Monarch.idl</DependentUpon>
</ClInclude>
<ClInclude Include="FindTargetWindowArgs.h">
<DependentUpon>Monarch.idl</DependentUpon>
</ClInclude>
<ClInclude Include="pch.h" />
<ClInclude Include="MonarchFactory.h" />
<ClInclude Include="Peasant.h">
@ -36,6 +39,9 @@
<ClCompile Include="Monarch.cpp">
<DependentUpon>Monarch.idl</DependentUpon>
</ClCompile>
<ClCompile Include="FindTargetWindowArgs.cpp">
<DependentUpon>Monarch.idl</DependentUpon>
</ClCompile>
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>

View file

@ -4,6 +4,7 @@
#include "pch.h"
#include "Monarch.h"
#include "CommandlineArgs.h"
#include "FindTargetWindowArgs.h"
#include "Monarch.g.cpp"
#include "../../types/inc/utils.hpp"
@ -117,6 +118,13 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
}
}
// TODO:MG This probably shouldn't be a public function. I'm making it
// public so the WindowManager can use it to manually tell the monarch it's
// own ID to use as the MRU, when the monarch is first instantiated. THat's
// dumb, but it's a hack to get something working.
//
// That was stupid. I knew it would be but yea it didn't work.
// THe Window manager doesn't have a peasant yet when it first creates the monarch.
void Monarch::_setMostRecentPeasant(const uint64_t peasantID)
{
// TODO:projects/5 Use a heap/priority queue per-desktop to track which
@ -126,6 +134,24 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
_mostRecentPeasant = peasantID;
}
uint64_t Monarch::_getMostRecentPeasantID()
{
if (_mostRecentPeasant == 0)
{
// We haven't yet been told the MRU peasant. Just use the first one.
// TODO: GOD this is just gonna be a random one. Hacks on hacks on hacks
if (_peasants.size() > 0)
{
return _peasants.begin()->second.GetID();
}
return 0;
}
else
{
return _mostRecentPeasant;
}
}
// Method Description:
// - Try to handle a commandline from a new WT invocation. We might need to
// hand the commandline to an existing window, or we might need to tell
@ -133,8 +159,10 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// Arguments:
// - <none>
// Return Value:
// - <none>
bool Monarch::ProposeCommandline(const Remoting::CommandlineArgs& /*args*/)
// - true if the caller should create a new window for this commandline.
// False otherwise - the monarch should have dispatched this commandline
// to another window in this case.
bool Monarch::ProposeCommandline(const Remoting::CommandlineArgs& args)
{
// TODO:projects/5
// The branch dev/migrie/f/remote-commandlines has a more complete
@ -142,6 +170,30 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// always want to create a new window, so we'll just return true. This
// will tell the caller that we didn't handle the commandline, and they
// should open a new window to deal with it themselves.
auto findWindowArgs = winrt::make_self<Remoting::implementation::FindTargetWindowArgs>();
findWindowArgs->Args(args);
_FindTargetWindowRequestedHandlers(*this, *findWindowArgs);
const auto targetWindow = findWindowArgs->ResultTargetWindow();
// TODO:projects/5 targetWindow==0 -> use the currently active window
if (targetWindow >= 0)
{
uint64_t windowID = ::base::saturated_cast<uint64_t>(targetWindow);
if (windowID == 0)
{
windowID = _getMostRecentPeasantID();
}
if (auto targetPeasant{ _getPeasant(windowID) })
{
targetPeasant.ExecuteCommandline(args);
return false;
}
}
// TEMPORARY: if the target window is -1, then we want a new window. All
// other cases, just do it in this window (for now).
// return targetWindow == -1;
return true;
}

View file

@ -39,6 +39,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
bool ProposeCommandline(const winrt::Microsoft::Terminal::Remoting::CommandlineArgs& args);
TYPED_EVENT(FindTargetWindowRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs);
private:
Monarch(const uint64_t testPID);
uint64_t _ourPID;
@ -51,6 +53,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
winrt::Microsoft::Terminal::Remoting::IPeasant _getPeasant(uint64_t peasantID);
void _setMostRecentPeasant(const uint64_t peasantID);
uint64_t _getMostRecentPeasantID();
void _peasantWindowActivated(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable& args);

View file

@ -5,11 +5,19 @@ import "Peasant.idl";
namespace Microsoft.Terminal.Remoting
{
[default_interface] runtimeclass FindTargetWindowArgs {
CommandlineArgs Args;
Int32 ResultTargetWindow;
}
[default_interface] runtimeclass Monarch {
Monarch();
UInt64 GetPID();
UInt64 AddPeasant(IPeasant peasant);
Boolean ProposeCommandline(CommandlineArgs args);
event Windows.Foundation.TypedEventHandler<Object, FindTargetWindowArgs> FindTargetWindowRequested;
};
}

View file

@ -106,10 +106,23 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
return;
}
// Here, we're the king!
//
// This is where you should do any aditional setup that might need to be
// done when we become the king. THis will be called both for the first
// window, and when the current monarch diesd.
// Wait, don't. Let's just have the monarch try/catch any accesses to
// peasants. If the peasant dies, then it can't get the peasant's
// anything. In that case, _remove it_.
_monarch.FindTargetWindowRequested({ this, &WindowManager::_raiseFindTargetWindowRequested });
// winrt::com_ptr<Remoting::implementation::Monarch> monarchImpl;
// monarchImpl.copy_from(winrt::get_self<Remoting::implementation::Monarch>(_monarch));
// if (monarchImpl)
// {
// monarchImpl->SetMostRecentPeasant(_peasant.GetID());
// }
}
bool WindowManager::_areWeTheKing()
@ -137,6 +150,9 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
if (_areWeTheKing())
{
// This is only called when a _new_ monarch is elected. We need to
// do this _always_, even on the first instance, which won't have an
// election
return true;
}
return false;
@ -213,4 +229,9 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
return _peasant;
}
void WindowManager::_raiseFindTargetWindowRequested(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs& args)
{
_FindTargetWindowRequestedHandlers(sender, args);
}
}

View file

@ -20,6 +20,10 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
winrt::Microsoft::Terminal::Remoting::Peasant CurrentWindow();
// Don't do this, the monarch can and will change over time
// FORWARDED_TYPED_EVENT(FindTargetWindowRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs, _monarch, FindTargetWindowRequested);
TYPED_EVENT(FindTargetWindowRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs);
private:
bool _shouldCreateWindow{ false };
DWORD _registrationHostClass{ 0 };
@ -39,6 +43,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
bool _electionNight2020();
void _createPeasantThread();
void _waitOnMonarchThread();
void _raiseFindTargetWindowRequested(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs& args);
};
}

View file

@ -1,4 +1,5 @@
import "Peasant.idl";
import "Monarch.idl";
namespace Microsoft.Terminal.Remoting
@ -9,5 +10,6 @@ namespace Microsoft.Terminal.Remoting
void ProposeCommandline(CommandlineArgs args);
Boolean ShouldCreateWindow { get; };
IPeasant CurrentWindow();
event Windows.Foundation.TypedEventHandler<Object, FindTargetWindowArgs> FindTargetWindowRequested;
};
}

View file

@ -1125,6 +1125,26 @@ namespace winrt::TerminalApp::implementation
return result; // TODO:MG does a return value make sense
}
int32_t AppLogic::FindTargetWindow(array_view<const winrt::hstring> args)
{
::TerminalApp::AppCommandlineArgs appArgs;
auto result = appArgs.ParseArgs(args);
if (result == 0)
{
// TODO:MG Right now, any successful parse will end up in the same window
return 0;
// TODO:projects/5 We'll want to use the windowingBehavior setting to determine
// well
// Maybe that'd be a special return value out of here, to tell the monarch to do something special
// -1 -> create a new window
// -2 -> find the mru, this desktop
// -3 -> MRU, any desktop
}
// Any unsuccessful parse will be a new window.
return -1;
}
// Method Description:
// - If there were any errors parsing the commandline that was used to
// initialize the terminal, this will return a string containing that

View file

@ -30,6 +30,7 @@ namespace winrt::TerminalApp::implementation
int32_t SetStartupCommandline(array_view<const winrt::hstring> actions);
int32_t ExecuteCommandline(array_view<const winrt::hstring> actions);
int32_t FindTargetWindow(array_view<const winrt::hstring> actions);
winrt::hstring ParseCommandlineMessage();
bool ShouldExitEarly();

View file

@ -56,6 +56,8 @@ namespace TerminalApp
UInt64 GetLastActiveControlTaskbarState();
UInt64 GetLastActiveControlTaskbarProgress();
Int32 FindTargetWindow(String[] args);
// See IDialogPresenter and TerminalPage's DialogPresenter for more
// information.
Windows.Foundation.IAsyncOperation<Windows.UI.Xaml.Controls.ContentDialogResult> ShowDialog(Windows.UI.Xaml.Controls.ContentDialog dialog);

View file

@ -30,6 +30,12 @@ AppHost::AppHost() noexcept :
{
_logic = _app.Logic(); // get a ref to app's logic
// Inform the WindowManager that it can use us to find the target window for
// a set of commandline args. This needs to be done before
// _HandleCommandlineArgs, because WE might end up being the monarch. That
// would mean we'd need to be responsible for looking that up.
_windowManager.FindTargetWindowRequested({ this, &AppHost::_FindTargetWindow });
// If there were commandline args to our process, try and process them here.
// Do this before AppLogic::Create, otherwise this will have no effect.
//
@ -521,3 +527,10 @@ void AppHost::_DispatchCommandline(winrt::Windows::Foundation::IInspectable /*se
{
_logic.ExecuteCommandline(args.Args());
}
void AppHost::_FindTargetWindow(const winrt::Windows::Foundation::IInspectable& /*sender*/,
const winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs& args)
{
const auto targetWindow = _logic.FindTargetWindow(args.Args().Args());
args.ResultTargetWindow(targetWindow);
}

View file

@ -47,4 +47,7 @@ private:
void _DispatchCommandline(winrt::Windows::Foundation::IInspectable sender,
winrt::Microsoft::Terminal::Remoting::CommandlineArgs args);
void _FindTargetWindow(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs& args);
};