From 4ae9b7e513fbb8b00dec7d444e9d67f6d2a7fa2a Mon Sep 17 00:00:00 2001 From: Russell Martin Date: Wed, 21 Aug 2024 16:56:53 -0400 Subject: [PATCH] Inform user of errors failing to initialize WebView - On Windows, if the callback for WebView initialization raises an exception, that exception is swallowed in .NET and not reported to the user. Now, the user is presented with a dialog box explaining the failure. --- changes/2779.bugfix.rst | 1 + winforms/src/toga_winforms/widgets/mapview.py | 13 ++++++++++--- winforms/src/toga_winforms/widgets/slider.py | 4 ++-- winforms/src/toga_winforms/widgets/webview.py | 13 +++++++++++-- 4 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 changes/2779.bugfix.rst diff --git a/changes/2779.bugfix.rst b/changes/2779.bugfix.rst new file mode 100644 index 0000000000..c568937e9e --- /dev/null +++ b/changes/2779.bugfix.rst @@ -0,0 +1 @@ +The WebView and MapView widgets now log an error if initialization fails. diff --git a/winforms/src/toga_winforms/widgets/mapview.py b/winforms/src/toga_winforms/widgets/mapview.py index a4a1e9f026..31a3d9c3fb 100644 --- a/winforms/src/toga_winforms/widgets/mapview.py +++ b/winforms/src/toga_winforms/widgets/mapview.py @@ -81,7 +81,7 @@ class MapView(Widget): def create(self): self.native = WebView2() # WebView has a 2 phase startup; the widget needs to be initialized, - # the the content needs to be loaded. We can't actually use the widget + # the content needs to be loaded. We can't actually use the widget # until the content is fully loaded. self.native.CoreWebView2InitializationCompleted += WeakrefCallable( self.winforms_initialization_completed @@ -141,11 +141,18 @@ def winforms_initialization_completed(self, sender, args): WinForms.MessageBoxIcon.Error, ) webbrowser.open( - "https://developer.microsoft.com/en-us/microsoft-edge/webview2/#download-section" + "https://developer.microsoft.com/en-us/microsoft-edge/webview2/#download" ) else: # pragma: nocover - raise RuntimeError(args.InitializationException) + WinForms.MessageBox.Show( + "A critical error has occurred and functionality may be impaired.\n\n" + "The WebView2 initialization failed with an exception:\n\n" + f"{args.InitializationException}", + "Error", + WinForms.MessageBoxButtons.OK, + WinForms.MessageBoxIcon.Error, + ) def winforms_navigation_completed(self, sender, args): # The Toga API allows you to invoke methods on the MapView as soon diff --git a/winforms/src/toga_winforms/widgets/slider.py b/winforms/src/toga_winforms/widgets/slider.py index 7d6c3481f1..09525d72f4 100644 --- a/winforms/src/toga_winforms/widgets/slider.py +++ b/winforms/src/toga_winforms/widgets/slider.py @@ -27,11 +27,11 @@ def create(self): # Unlike Scroll, ValueChanged also fires when the value is changed # programmatically, such as via the testbed probe. - self.native.ValueChanged += WeakrefCallable(self.winforms_value_chaned) + self.native.ValueChanged += WeakrefCallable(self.winforms_value_changed) self.native.MouseDown += WeakrefCallable(self.winforms_mouse_down) self.native.MouseUp += WeakrefCallable(self.winforms_mouse_up) - def winforms_value_chaned(self, sender, event): + def winforms_value_changed(self, sender, event): self.on_change() def winforms_mouse_down(self, sender, event): diff --git a/winforms/src/toga_winforms/widgets/webview.py b/winforms/src/toga_winforms/widgets/webview.py index 7c543e97d8..7756f5e776 100644 --- a/winforms/src/toga_winforms/widgets/webview.py +++ b/winforms/src/toga_winforms/widgets/webview.py @@ -76,6 +76,7 @@ def winforms_initialization_completed(self, sender, args): self.default_user_agent = settings.UserAgent debug = True + settings.AreBrowserAcceleratorKeysEnabled = debug settings.AreDefaultContextMenusEnabled = debug settings.AreDefaultScriptDialogsEnabled = True settings.AreDevToolsEnabled = debug @@ -83,6 +84,7 @@ def winforms_initialization_completed(self, sender, args): settings.IsScriptEnabled = True settings.IsWebMessageEnabled = True settings.IsStatusBarEnabled = debug + settings.IsSwipeNavigationEnabled = False settings.IsZoomControlEnabled = True for task in self.pending_tasks: @@ -108,11 +110,18 @@ def winforms_initialization_completed(self, sender, args): WinForms.MessageBoxIcon.Error, ) webbrowser.open( - "https://developer.microsoft.com/en-us/microsoft-edge/webview2/#download-section" + "https://developer.microsoft.com/en-us/microsoft-edge/webview2/#download" ) else: # pragma: nocover - raise RuntimeError(args.InitializationException) + WinForms.MessageBox.Show( + "A critical error has occurred and functionality may be impaired.\n\n" + "The WebView2 initialization failed with an exception:\n\n" + f"{args.InitializationException}", + "Error", + WinForms.MessageBoxButtons.OK, + WinForms.MessageBoxIcon.Error, + ) def winforms_navigation_completed(self, sender, args): self.interface.on_webview_load()