Skip to content

Commit

Permalink
Ask the TerminalApp to parse the commandline, and tell us what the wi…
Browse files Browse the repository at this point in the history
…ndow should be. It just always says 0 for now, but in the future it could actually give us useful info.
  • Loading branch information
zadjii-msft committed Jan 6, 2021
1 parent 00184e7 commit 658db6b
Show file tree
Hide file tree
Showing 14 changed files with 161 additions and 2 deletions.
5 changes: 5 additions & 0 deletions src/cascadia/Remoting/FindTargetWindowArgs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "FindTargetWindowArgs.h"
#include "FindTargetWindowArgs.g.cpp"
17 changes: 17 additions & 0 deletions src/cascadia/Remoting/FindTargetWindowArgs.h
Original file line number Diff line number Diff line change
@@ -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);
};
}
6 changes: 6 additions & 0 deletions src/cascadia/Remoting/Microsoft.Terminal.RemotingLib.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand All @@ -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>
Expand Down
56 changes: 54 additions & 2 deletions src/cascadia/Remoting/Monarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand All @@ -126,22 +134,66 @@ 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
// the caller that they need to become a new window to handle it themselves.
// 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
// version of this function, with a naive implementation. For now, we
// 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;
}

Expand Down
3 changes: 3 additions & 0 deletions src/cascadia/Remoting/Monarch.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down
8 changes: 8 additions & 0 deletions src/cascadia/Remoting/Monarch.idl
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
}
21 changes: 21 additions & 0 deletions src/cascadia/Remoting/WindowManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}
6 changes: 6 additions & 0 deletions src/cascadia/Remoting/WindowManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand All @@ -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);
};
}

Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/Remoting/WindowManager.idl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import "Peasant.idl";
import "Monarch.idl";


namespace Microsoft.Terminal.Remoting
Expand All @@ -9,5 +10,6 @@ namespace Microsoft.Terminal.Remoting
void ProposeCommandline(CommandlineArgs args);
Boolean ShouldCreateWindow { get; };
IPeasant CurrentWindow();
event Windows.Foundation.TypedEventHandler<Object, FindTargetWindowArgs> FindTargetWindowRequested;
};
}
20 changes: 20 additions & 0 deletions src/cascadia/TerminalApp/AppLogic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalApp/AppLogic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalApp/AppLogic.idl
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
13 changes: 13 additions & 0 deletions src/cascadia/WindowsTerminal/AppHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
//
Expand Down Expand Up @@ -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);
}
3 changes: 3 additions & 0 deletions src/cascadia/WindowsTerminal/AppHost.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,7 @@ class AppHost

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);
};

1 comment on commit 658db6b

@github-actions

This comment was marked as outdated.

Please sign in to comment.