From f96b7a56ee637aa51e570b99bd5407cd0bce236a Mon Sep 17 00:00:00 2001 From: Tian L <60599517+tian-lt@users.noreply.github.com> Date: Sun, 28 Apr 2024 22:13:13 +0800 Subject: [PATCH] Cherry-pick for 2403 (#2166) * Fix #2146: SWIPE DELETE FUNCTION FREEZES APP (#2157) * fix stackoverflow * space * Multi-instance (#2161) * launch multi instances * trace error * simplify the graphing test * remove an assertion * simplify some code * remove some trivial code. * fix runtime cast * Resize on the first launch (#2165) --- src/CalcViewModel/Common/NavCategory.cpp | 33 +- src/Calculator/App.xaml.cs | 416 +++----------------- src/Calculator/Calculator.csproj | 1 - src/Calculator/Package.Release.appxmanifest | 15 +- src/Calculator/Package.appxmanifest | 15 +- src/Calculator/Views/Calculator.xaml.cs | 11 +- src/Calculator/WindowFrameService.cs | 189 --------- 7 files changed, 85 insertions(+), 595 deletions(-) delete mode 100644 src/Calculator/WindowFrameService.cs diff --git a/src/CalcViewModel/Common/NavCategory.cpp b/src/CalcViewModel/Common/NavCategory.cpp index 829f7488..c8e5185e 100644 --- a/src/CalcViewModel/Common/NavCategory.cpp +++ b/src/CalcViewModel/Common/NavCategory.cpp @@ -50,34 +50,19 @@ static constexpr int GRAPHING_ID = 17; namespace // put the utils within this TU { Platform::String^ CurrentUserId; - std::mutex GraphingModeCheckMutex; bool IsGraphingModeEnabled() { - static bool isChecked = false; - static bool isEnabled = false; - - std::scoped_lock lock(GraphingModeCheckMutex); - if (isChecked) - { - return isEnabled; - } - else + static auto enabled = [] { auto user = User::GetFromId(CurrentUserId); if (user == nullptr) { return true; } - - auto namedPolicyData = NamedPolicy::GetPolicyFromPathForUser( - user, - L"Education", - L"AllowGraphingCalculator"); - isEnabled = namedPolicyData->GetBoolean(); - isChecked = true; - return isEnabled; - } + return NamedPolicy::GetPolicyFromPathForUser(user, L"Education", L"AllowGraphingCalculator")->GetBoolean(); + }(); + return enabled; } // The order of items in this list determines the order of items in the menu. @@ -318,7 +303,6 @@ NavCategoryGroup::NavCategoryGroup(const NavCategoryGroupInitializer& groupIniti void NavCategoryStates::SetCurrentUser(Platform::String^ userId) { - std::scoped_lock lock(GraphingModeCheckMutex); CurrentUserId = userId; } @@ -518,13 +502,6 @@ bool NavCategoryStates::IsValidViewMode(ViewMode mode) bool NavCategoryStates::IsViewModeEnabled(ViewMode mode) { - if (mode != ViewMode::Graphing) - { - return true; - } - else - { - return IsGraphingModeEnabled(); - } + return mode != ViewMode::Graphing ? true : IsGraphingModeEnabled(); } diff --git a/src/Calculator/App.xaml.cs b/src/Calculator/App.xaml.cs index 84d75e10..8ca14222 100644 --- a/src/Calculator/App.xaml.cs +++ b/src/Calculator/App.xaml.cs @@ -6,37 +6,24 @@ // Declaration of the App class. // -using CalculatorApp.ViewModel.Common; -using CalculatorApp.ViewModel.Common.Automation; - using System; -using System.Collections.Generic; using System.Diagnostics; -using System.Threading; using System.Threading.Tasks; using Windows.ApplicationModel; using Windows.ApplicationModel.Activation; -using Windows.ApplicationModel.Core; -using Windows.Foundation; using Windows.Storage; -using Windows.UI.Core; using Windows.UI.StartScreen; using Windows.UI.ViewManagement; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; +using CalculatorApp.Utils; +using CalculatorApp.ViewModel.Common; +using CalculatorApp.ViewModel.Common.Automation; + namespace CalculatorApp { - namespace ApplicationResourceKeys - { - public static class Globals - { - public static readonly string AppMinWindowHeight = "AppMinWindowHeight"; - public static readonly string AppMinWindowWidth = "AppMinWindowWidth"; - } - } - /// /// Provides application-specific behavior to supplement the default Application class. /// @@ -49,17 +36,12 @@ namespace CalculatorApp public App() { InitializeComponent(); - - m_preLaunched = false; - - RegisterDependencyProperties(); + NarratorNotifier.RegisterDependencyProperties(); // TODO: MSFT 14645325: Set this directly from XAML. // Currently this is bugged so the property is only respected from code-behind. HighContrastAdjustment = ApplicationHighContrastAdjustment.None; - Suspending += OnSuspending; - #if DEBUG DebugSettings.IsBindingTracingEnabled = true; DebugSettings.BindingFailed += (sender, args) => @@ -81,18 +63,12 @@ namespace CalculatorApp /// Details about the launch request and process. protected override void OnLaunched(LaunchActivatedEventArgs args) { - if (args.PrelaunchActivated) - { - // If the app got pre-launch activated, then save that state in a flag - m_preLaunched = true; - } - NavCategoryStates.SetCurrentUser(args.User.NonRoamableId); - // It takes time to check GraphingMode at the 1st time. So, do it in a background thread + // It takes time to check GraphingMode at the very first time. Warm up in a background thread. Task.Run(() => NavCategoryStates.IsViewModeEnabled(ViewMode.Graphing)); - OnAppLaunch(args, args.Arguments); + OnAppLaunch(args, args.Arguments, args.PrelaunchActivated); } protected override void OnActivated(IActivatedEventArgs args) @@ -101,76 +77,36 @@ namespace CalculatorApp { // We currently don't pass the uri as an argument, // and handle any protocol launch as a normal app launch. - OnAppLaunch(args, null); + OnAppLaunch(args, null, false); } } - internal void RemoveWindow(WindowFrameService frameService) - { - // Shell does not allow killing the main window. - if (m_mainViewId != frameService.GetViewId()) - { - _ = HandleViewReleaseAndRemoveWindowFromMap(frameService); - } - } - - internal void RemoveSecondaryWindow(WindowFrameService frameService) - { - // Shell does not allow killing the main window. - if (m_mainViewId != frameService.GetViewId()) - { - RemoveWindowFromMap(frameService.GetViewId()); - } - } - - private static Frame CreateFrame() - { - var frame = new Frame - { - FlowDirection = LocalizationService.GetInstance().GetFlowDirection() - }; - return frame; - } - - private static void SetMinWindowSizeAndThemeAndActivate(Frame rootFrame, Size minWindowSize) - { - // SetPreferredMinSize should always be called before Window.Activate - ApplicationView appView = ApplicationView.GetForCurrentView(); - appView.SetPreferredMinSize(minWindowSize); - - // Place the frame in the current Window - Window.Current.Content = rootFrame; - CalculatorApp.Utils.ThemeHelper.InitializeAppTheme(); - Window.Current.Activate(); - } - - private void OnAppLaunch(IActivatedEventArgs args, string argument) + private void OnAppLaunch(IActivatedEventArgs args, string argument, bool isPreLaunch) { // Uncomment the following lines to display frame-rate and per-frame CPU usage info. - //#if _DEBUG + //#if DEBUG // if (IsDebuggerPresent()) // { - // DebugSettings->EnableFrameRateCounter = true; + // DebugSettings.EnableFrameRateCounter = true; // } //#endif - args.SplashScreen.Dismissed += DismissedEventHandler; + args.SplashScreen.Dismissed += async (_, __) => await SetupJumpListAsync(); - var rootFrame = (Window.Current.Content as Frame); - WeakReference weak = new WeakReference(this); + var minWindowWidth = Convert.ToSingle(Resources["AppMinWindowWidth"]); + var minWindowHeight = Convert.ToSingle(Resources["AppMinWindowHeight"]); + var minWindowSize = SizeHelper.FromDimensions(minWindowWidth, minWindowHeight); + var appView = ApplicationView.GetForCurrentView(); + var localSettings = ApplicationData.Current.LocalSettings; - float minWindowWidth = (float)((double)Resources[ApplicationResourceKeys.Globals.AppMinWindowWidth]); - float minWindowHeight = (float)((double)Resources[ApplicationResourceKeys.Globals.AppMinWindowHeight]); - Size minWindowSize = SizeHelper.FromDimensions(minWindowWidth, minWindowHeight); + // SetPreferredMinSize should always be called before Window.Activate + appView.SetPreferredMinSize(minWindowSize); - ApplicationView appView = ApplicationView.GetForCurrentView(); - ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings; // For very first launch, set the size of the calc as size of the default standard mode if (!localSettings.Values.ContainsKey("VeryFirstLaunch")) { localSettings.Values["VeryFirstLaunch"] = false; - appView.SetPreferredMinSize(minWindowSize); - appView.TryResizeView(minWindowSize); + appView.TryResizeView(minWindowSize); // the requested size must not be less than the min size. } else { @@ -179,190 +115,34 @@ namespace CalculatorApp // Do not repeat app initialization when the Window already has content, // just ensure that the window is active + var rootFrame = Window.Current.Content as Frame; if (rootFrame == null) { - if (!Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons")) // PC Family + rootFrame = new Frame { - // Disable the system view activation policy during the first launch of the app - // only for PC family devices and not for phone family devices - try - { - ApplicationViewSwitcher.DisableSystemViewActivationPolicy(); - } - catch (Exception) - { - // Log that DisableSystemViewActionPolicy didn't work - } - } - - // Create a Frame to act as the navigation context - rootFrame = App.CreateFrame(); - - // When the navigation stack isn't restored navigate to the first page, - // configuring the new page by passing required information as a navigation - // parameter - if (!rootFrame.Navigate(typeof(MainPage), argument)) - { - // We couldn't navigate to the main page, kill the app so we have a good - // stack to debug - throw new SystemException(); - } - - SetMinWindowSizeAndThemeAndActivate(rootFrame, minWindowSize); - m_mainViewId = ApplicationView.GetForCurrentView().Id; - AddWindowToMap(WindowFrameService.CreateNewWindowFrameService(rootFrame, false, weak)); + FlowDirection = LocalizationService.GetInstance().GetFlowDirection() + }; } - else + + if (isPreLaunch) { - // For first launch, LaunchStart is logged in constructor, this is for subsequent launches. - - // !Phone check is required because even in continuum mode user interaction mode is Mouse not Touch - if ((UIViewSettings.GetForCurrentView().UserInteractionMode == UserInteractionMode.Mouse) - && (!Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons"))) - { - // If the pre-launch hasn't happened then allow for the new window/view creation - if (!m_preLaunched) - { - var newCoreAppView = CoreApplication.CreateNewView(); - _ = newCoreAppView.Dispatcher.RunAsync( - CoreDispatcherPriority.Normal, async () => - { - if (weak.Target is App that) - { - var newRootFrame = App.CreateFrame(); - - SetMinWindowSizeAndThemeAndActivate(newRootFrame, minWindowSize); - - if (!newRootFrame.Navigate(typeof(MainPage), argument)) - { - // We couldn't navigate to the main page, kill the app so we have a good - // stack to debug - throw new SystemException(); - } - - var frameService = WindowFrameService.CreateNewWindowFrameService(newRootFrame, true, weak); - that.AddWindowToMap(frameService); - - var dispatcher = CoreWindow.GetForCurrentThread().Dispatcher; - - // CSHARP_MIGRATION_ANNOTATION: - // class SafeFrameWindowCreation is being interpreted into a IDisposable class - // in order to enhance its RAII capability that was written in C++/CX - using (var safeFrameServiceCreation = new SafeFrameWindowCreation(frameService, that)) - { - int newWindowId = ApplicationView.GetApplicationViewIdForWindow(CoreWindow.GetForCurrentThread()); - - ActivationViewSwitcher activationViewSwitcher = null; - var activateEventArgs = (args as IViewSwitcherProvider); - if (activateEventArgs != null) - { - activationViewSwitcher = activateEventArgs.ViewSwitcher; - } - - if (activationViewSwitcher != null) - { - _ = activationViewSwitcher.ShowAsStandaloneAsync(newWindowId, ViewSizePreference.Default); - safeFrameServiceCreation.SetOperationSuccess(true); - } - else - { - var activatedEventArgs = (args as IApplicationViewActivatedEventArgs); - if ((activatedEventArgs != null) && (activatedEventArgs.CurrentlyShownApplicationViewId != 0)) - { - // CSHARP_MIGRATION_ANNOTATION: - // here we don't use ContinueWith() to interpret origin code because we would like to - // pursue the design of class SafeFrameWindowCreate whichi was using RAII to ensure - // some states get handled properly when its instance is being destructed. - // - // To achieve that, SafeFrameWindowCreate has been reinterpreted using IDisposable - // pattern, which forces we use below way to keep async works being controlled within - // a same code block. - var viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync( - frameService.GetViewId(), - ViewSizePreference.Default, - activatedEventArgs.CurrentlyShownApplicationViewId, - ViewSizePreference.Default); - // SafeFrameServiceCreation is used to automatically remove the frame - // from the list of frames if something goes bad. - safeFrameServiceCreation.SetOperationSuccess(viewShown); - } - } - } - } - }); - } - else - { - ActivationViewSwitcher activationViewSwitcher = null; - var activateEventArgs = (args as IViewSwitcherProvider); - if (activateEventArgs != null) - { - activationViewSwitcher = activateEventArgs.ViewSwitcher; - } - - if (activationViewSwitcher != null) - { - _ = activationViewSwitcher.ShowAsStandaloneAsync( - ApplicationView.GetApplicationViewIdForWindow(CoreWindow.GetForCurrentThread()), ViewSizePreference.Default); - } - else - { - TraceLogger.GetInstance().LogError(ViewMode.None, "App.OnAppLaunch", "Null_ActivationViewSwitcher"); - } - } - // Set the preLaunched flag to false - m_preLaunched = false; - } - else // for touch devices - { - if (rootFrame.Content == null) - { - // When the navigation stack isn't restored navigate to the first page, - // configuring the new page by passing required information as a navigation - // parameter - if (!rootFrame.Navigate(typeof(MainPage), argument)) - { - // We couldn't navigate to the main page, - // kill the app so we have a good stack to debug - throw new SystemException(); - } - } - if (ApplicationView.GetForCurrentView().ViewMode != ApplicationViewMode.CompactOverlay) - { - if (!Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons")) - { - // for tablet mode: since system view activation policy is disabled so do ShowAsStandaloneAsync if activationViewSwitcher exists in - // activationArgs - ActivationViewSwitcher activationViewSwitcher = null; - var activateEventArgs = (args as IViewSwitcherProvider); - if (activateEventArgs != null) - { - activationViewSwitcher = activateEventArgs.ViewSwitcher; - } - if (activationViewSwitcher != null) - { - var viewId = (args as IApplicationViewActivatedEventArgs).CurrentlyShownApplicationViewId; - if (viewId != 0) - { - _ = activationViewSwitcher.ShowAsStandaloneAsync(viewId); - } - } - } - // Ensure the current window is active - Window.Current.Activate(); - } - } + return; } - } - private void DismissedEventHandler(SplashScreen sender, object e) - { - _ = SetupJumpList(); - } + // When the navigation stack isn't restored navigate to the first page, + // configuring the new page by passing required information as a navigation + // parameter + if (rootFrame.Content == null && !rootFrame.Navigate(typeof(MainPage), argument)) + { + // We couldn't navigate to the main page, kill the app so we have a good + // stack to debug + throw new SystemException("6d430286-eb5d-4f8d-95d2-3d1059552968"); + } - private void RegisterDependencyProperties() - { - NarratorNotifier.RegisterDependencyProperties(); + // Place the frame in the current Window + Window.Current.Content = rootFrame; + ThemeHelper.InitializeAppTheme(); + Window.Current.Activate(); } private void OnSuspending(object sender, SuspendingEventArgs args) @@ -370,43 +150,7 @@ namespace CalculatorApp TraceLogger.GetInstance().LogButtonUsage(); } - private sealed class SafeFrameWindowCreation : IDisposable - { - public SafeFrameWindowCreation(WindowFrameService frameService, App parent) - { - m_frameService = frameService; - m_frameOpenedInWindow = false; - m_parent = parent; - } - - public void SetOperationSuccess(bool success) - { - m_frameOpenedInWindow = success; - } - - public void Dispose() - { - if (!m_frameOpenedInWindow) - { - // Close the window as the navigation to the window didn't succeed - // and this is not visible to the user. - m_parent.RemoveWindowFromMap(m_frameService.GetViewId()); - } - - GC.SuppressFinalize(this); - } - - ~SafeFrameWindowCreation() - { - Dispose(); - } - - private readonly WindowFrameService m_frameService; - private bool m_frameOpenedInWindow; - private readonly App m_parent; - }; - - private async Task SetupJumpList() + private async Task SetupJumpListAsync() { try { @@ -426,87 +170,19 @@ namespace CalculatorApp var item = JumpListItem.CreateWithArguments(((int)mode).ToString(), "ms-resource:///Resources/" + NavCategoryStates.GetNameResourceKey(mode)); item.Description = "ms-resource:///Resources/" + NavCategoryStates.GetNameResourceKey(mode); item.Logo = new Uri("ms-appx:///Assets/" + mode + ".png"); - jumpList.Items.Add(item); } await jumpList.SaveAsync(); } - catch + catch (Exception ex) { + TraceLogger.GetInstance().LogError(ViewMode.None, nameof(SetupJumpListAsync), ex.ToString()); +#if DEBUG + throw; +#endif } } - - private async Task HandleViewReleaseAndRemoveWindowFromMap(WindowFrameService frameService) - { - WeakReference weak = new WeakReference(this); - - // Unregister the event handler of the Main Page - var frame = (Window.Current.Content as Frame); - var mainPage = (frame.Content as MainPage); - - mainPage.UnregisterEventHandlers(); - - await frameService.HandleViewRelease(); - await Task.Run(() => - { - var that = weak.Target as App; - that.RemoveWindowFromMap(frameService.GetViewId()); - }).ConfigureAwait(false /* task_continuation_context::use_arbitrary() */); - } - - private void AddWindowToMap(WindowFrameService frameService) - { - m_windowsMapLock.EnterWriteLock(); - try - { - m_secondaryWindows[frameService.GetViewId()] = frameService; - TraceLogger.GetInstance().UpdateWindowCount(Convert.ToUInt64(m_secondaryWindows.Count)); - } - finally - { - m_windowsMapLock.ExitWriteLock(); - } - } - - private WindowFrameService GetWindowFromMap(int viewId) - { - m_windowsMapLock.EnterReadLock(); - try - { - if (m_secondaryWindows.TryGetValue(viewId, out var windowMapEntry)) - { - return windowMapEntry; - } - else - { - return null; - } - } - finally - { - m_windowsMapLock.ExitReadLock(); - } - } - - private void RemoveWindowFromMap(int viewId) - { - m_windowsMapLock.EnterWriteLock(); - try - { - bool removed = m_secondaryWindows.Remove(viewId); - Debug.Assert(removed != false, "Window does not exist in the list"); - } - finally - { - m_windowsMapLock.ExitWriteLock(); - } - } - - private readonly ReaderWriterLockSlim m_windowsMapLock = new ReaderWriterLockSlim(); - private readonly Dictionary m_secondaryWindows = new Dictionary(); - private int m_mainViewId; - private bool m_preLaunched; } } diff --git a/src/Calculator/Calculator.csproj b/src/Calculator/Calculator.csproj index e9f71be3..b92f52fd 100644 --- a/src/Calculator/Calculator.csproj +++ b/src/Calculator/Calculator.csproj @@ -250,7 +250,6 @@ UnitConverter.xaml - diff --git a/src/Calculator/Package.Release.appxmanifest b/src/Calculator/Package.Release.appxmanifest index c71a8cbe..57f7e108 100644 --- a/src/Calculator/Package.Release.appxmanifest +++ b/src/Calculator/Package.Release.appxmanifest @@ -1,5 +1,12 @@ - + @@ -14,7 +21,11 @@ - + diff --git a/src/Calculator/Package.appxmanifest b/src/Calculator/Package.appxmanifest index 515c8ee9..901b0453 100644 --- a/src/Calculator/Package.appxmanifest +++ b/src/Calculator/Package.appxmanifest @@ -1,5 +1,12 @@ - + @@ -14,7 +21,11 @@ - + diff --git a/src/Calculator/Views/Calculator.xaml.cs b/src/Calculator/Views/Calculator.xaml.cs index 32b70fa0..ccd42637 100644 --- a/src/Calculator/Views/Calculator.xaml.cs +++ b/src/Calculator/Views/Calculator.xaml.cs @@ -189,7 +189,6 @@ namespace CalculatorApp } } - public void UpdatePanelViewState() { UpdateHistoryState(); @@ -772,7 +771,10 @@ namespace CalculatorApp private void SetChildAsMemory() { - DockMemoryHolder.Child = GetMemory(); + if (DockMemoryHolder.Child != GetMemory()) + { + DockMemoryHolder.Child = GetMemory(); + } } private void SetChildAsHistory() @@ -782,7 +784,10 @@ namespace CalculatorApp InitializeHistoryView(Model.HistoryVM); } - DockHistoryHolder.Child = m_historyList; + if (DockHistoryHolder.Child != m_historyList) + { + DockHistoryHolder.Child = m_historyList; + } } private Memory GetMemory() diff --git a/src/Calculator/WindowFrameService.cs b/src/Calculator/WindowFrameService.cs deleted file mode 100644 index 55f5c7d8..00000000 --- a/src/Calculator/WindowFrameService.cs +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using CalculatorApp.Common; -using CalculatorApp.ViewModel.Common; - -using System; -using System.Collections.Generic; -using System.Data; -using System.Diagnostics; -using System.Threading.Tasks; - -using Windows.ApplicationModel.Core; -using Windows.UI.Core; -using Windows.UI.ViewManagement; -using Windows.UI.Xaml; -using Windows.UI.Xaml.Controls; - -namespace CalculatorApp -{ - public sealed class WindowFrameService - { - public Page GetCurrentPage() - { - return (m_frame.Content as Page); - } - - public void SetNewFrame(Windows.UI.Xaml.Controls.Frame frame) - { - Debug.Assert(frame.BackStackDepth == 0); - m_frame = frame; - } - - // createdByUs means any window that we create. - // !createdByUs means the main window - internal static WindowFrameService CreateNewWindowFrameService(Frame viewFrame, bool createdByUs, WeakReference parent) - { - Debug.Assert(CoreWindow.GetForCurrentThread() != null); - var frameService = new WindowFrameService(viewFrame, parent); - frameService.InitializeFrameService(createdByUs); - return frameService; - } - - public CoreDispatcher GetCoreDispatcher() - { - return m_coreDispatcher; - } - - public int GetViewId() - { - return m_viewId; - } - - public void RegisterOnWindowClosingHandler(Action onWindowClosingHandler) - { - m_onWindowClosingHandlers.Add(onWindowClosingHandler); - } - - public Task HandleViewRelease() - { - TaskCompletionSource tsource = new TaskCompletionSource(); - _ = m_coreDispatcher.RunAsync(CoreDispatcherPriority.Low, () => - { - KeyboardShortcutManager.OnWindowClosed(this.m_viewId); - Window.Current.Content = null; - this.InvokeWindowClosingHandlers(); - // This is to ensure InvokeWindowClosingHandlers is be done before RemoveWindowFromMap - // If InvokeWindowClosingHandlers throws any exception we want it to crash the application - // so we are OK not setting closingHandlersCompletedEvent in that case - tsource.SetResult(new object()); - this.m_coreDispatcher.StopProcessEvents(); - Window.Current.Close(); - }); - - return tsource.Task; - } - - // Throws InvalidArgumentException if a service is already registered with the specified id - public void RegisterRuntimeWindowService(Type serviceId, object service) - { - if (TryResolveRuntimeWindowService(serviceId) != null) - { - throw new DuplicateNameException(serviceId + " already registered"); - } - - m_runtimeServicesMap[serviceId.Name] = service; - } - - // Returns false if no service was registered with the specified id - public bool RemoveRuntimeWindowService(Type serviceId) - { - return m_runtimeServicesMap.Remove(serviceId.Name); - } - - // Throws InvalidArgumentException if no service is registered with the specified id - public object ResolveRuntimeWindowService(Type serviceId) - { - var service = TryResolveRuntimeWindowService(serviceId); - - if (service != null) - { - return service; - } - else - { - throw new EntryPointNotFoundException(serviceId.Name + " not found"); - } - } - - public Frame GetFrame() - { - return m_frame; - } - - public void InvokeWindowClosingHandlers() - { - // Should be called only once just before we kill the window. - foreach (var handler in m_onWindowClosingHandlers) - { - handler(); - } - m_onWindowClosingHandlers.Clear(); - } - - private WindowFrameService(Frame frame, WeakReference parent) - { - m_currentWindow = CoreWindow.GetForCurrentThread(); - m_coreDispatcher = m_currentWindow.Dispatcher; - m_frame = frame; - m_parent = parent; - m_viewId = ApplicationView.GetApplicationViewIdForWindow(m_currentWindow); - } - - private void InitializeFrameService(bool createdByUs) - { - Debug.Assert(createdByUs == (!CoreApplication.GetCurrentView().IsHosted && !CoreApplication.GetCurrentView().IsMain)); - if (createdByUs) - { - ApplicationView.GetForCurrentView().Consolidated += OnConsolidated; - } - else - { - CoreWindow.GetForCurrentThread().Closed += OnClosed; - } - } - - private void OnConsolidated(ApplicationView sender, ApplicationViewConsolidatedEventArgs e) - { - TraceLogger.GetInstance().DecreaseWindowCount(); - if (m_parent.IsAlive) - { - var parent = m_parent.Target as App; - parent.RemoveWindow(this); - } - } - - private void OnClosed(CoreWindow sender, CoreWindowEventArgs args) - { - if (m_parent.IsAlive) - { - var parent = m_parent.Target as App; - parent.RemoveSecondaryWindow(this); - } - } - - // Returns nullptr if no service is registered with the specified id - private object TryResolveRuntimeWindowService(Type serviceId) - { - if (m_runtimeServicesMap.TryGetValue(serviceId.Name, out object retval)) - { - return retval; - } - else - { - return null; - } - } - - private readonly Windows.UI.Core.CoreWindow m_currentWindow; - private readonly Windows.UI.Core.CoreDispatcher m_coreDispatcher; - private Windows.UI.Xaml.Controls.Frame m_frame; - private readonly int m_viewId; - private readonly WeakReference m_parent; - - private readonly Dictionary m_runtimeServicesMap = new Dictionary(); - private readonly List m_onWindowClosingHandlers = new List(); - } -} -