From 4b22963f9d3b5da04f560ecb0fd9827b9a12ce2e Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 14 Feb 2023 09:18:48 -0600 Subject: [PATCH] notes --- src/cascadia/TerminalControl/TermControl.cpp | 1 + src/cascadia/TerminalControl/TermControl.h | 8 ++------ src/cascadia/inc/cppwinrt_utils.h | 21 ++++++++++++++++++++ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 26d2b9712ed..c0f31c66a8b 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -93,6 +93,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation _revokers.interactivityOpenHyperlink = _interactivity.OpenHyperlink(winrt::auto_revoke, { get_weak(), &TermControl::_HyperlinkHandler }); _revokers.interactivityScrollPositionChanged = _interactivity.ScrollPositionChanged(winrt::auto_revoke, { get_weak(), &TermControl::_ScrollPositionChanged }); + // "Bubbled" events - ones we want to handle, by raising our own event. _revokers.CopyToClipboard = _core.CopyToClipboard(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleCopyToClipboard }); _revokers.TitleChanged = _core.TitleChanged(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleTitleChanged }); _revokers.TabColorChanged = _core.TabColorChanged(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleTabColorChanged }); diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 4a4d41cac73..acb4d95c1e4 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -139,16 +139,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation void AdjustOpacity(const double opacity, const bool relative); WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler); - -// Same thing, but handler is a projected type, not an implementation -#define BUBBLED_FORWARDED_TYPED_EVENT(name, sender, args) \ - TYPED_EVENT(name, sender, args) \ - void _bubble##name(const sender& s, const args& a) { _##name##Handlers(s, a); } - // -------------------------------- WinRT Events --------------------------------- // clang-format off WINRT_CALLBACK(FontSizeChanged, Control::FontSizeChangedEventArgs); + // UNDER NO CIRCUMSTANCES SHOULD YOU ADD A (PROJECTED_)FORWARDED_TYPED_EVENT HERE + BUBBLED_FORWARDED_TYPED_EVENT(CopyToClipboard, IInspectable, Control::CopyToClipboardEventArgs); BUBBLED_FORWARDED_TYPED_EVENT(TitleChanged, IInspectable, Control::TitleChangedEventArgs); BUBBLED_FORWARDED_TYPED_EVENT(TabColorChanged, IInspectable, IInspectable); diff --git a/src/cascadia/inc/cppwinrt_utils.h b/src/cascadia/inc/cppwinrt_utils.h index 1e9ccb1a0d0..ec6c1003877 100644 --- a/src/cascadia/inc/cppwinrt_utils.h +++ b/src/cascadia/inc/cppwinrt_utils.h @@ -102,6 +102,27 @@ public: winrt::event_token name(const Windows::Foundation::TypedEventHandler& h) { return handler.handlerName(h); } \ void name(const winrt::event_token& token) noexcept { handler.handlerName(token); } +// This is a bit like *FORWARDED_TYPED_EVENT. When you use a forwarded event, +// the handler gets added to the object that's raising the event. For example, +// the TerminalPage might be the handler for the TermControl's +// BackgroundColorChanged event, which is actually implemented by the +// ControlCore. So when Core raises an event, it immediately calls the handler +// on the Page. +// +// Instead, the BUBBELD eventk introduces an indirection layer. In the above +// example, the Core would raise the event, but now the Control would handle it, +// and raise an event with each of its own handlers. +// +// This allows us to detach the core from the control safely, witout needing to +// re-wire all the event handlers from page->control again. +// +// Implement like: +// +// _core.TitleChanged({ get_weak(), &TermControl::_bubbleTitleChanged }); +#define BUBBLED_FORWARDED_TYPED_EVENT(name, sender, args) \ + TYPED_EVENT(name, sender, args) \ + void _bubble##name(const sender& s, const args& a) { _##name##Handlers(s, a); } + // Use this macro to quick implement both the getter and setter for a property. // This should only be used for simple types where there's no logic in the // getter/setter beyond just accessing/updating the value.