From d1681162a68adb8af47328aaa3c15e5841c9b126 Mon Sep 17 00:00:00 2001 From: amaitland Date: Fri, 2 Jun 2017 11:47:24 +1000 Subject: [PATCH] WPF - Manually calculate GetScreenPoint Using PointToScreen(point) on the UI thread (had to be called in a sync fashion) made it easy for users to cause a deadlock Resolve #1915 --- CefSharp.Wpf/ChromiumWebBrowser.cs | 40 ++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/CefSharp.Wpf/ChromiumWebBrowser.cs b/CefSharp.Wpf/ChromiumWebBrowser.cs index 84e095653a..c7a72af083 100644 --- a/CefSharp.Wpf/ChromiumWebBrowser.cs +++ b/CefSharp.Wpf/ChromiumWebBrowser.cs @@ -82,6 +82,15 @@ public class ChromiumWebBrowser : ContentControl, IRenderWebBrowser, IWpfWebBrow /// The dispose count /// private int disposeCount; + /// + /// + /// Location of the control on the screen, relative to Top/Left + /// Used to calculate GetScreenPoint + /// We're unable to call PointToScreen directly due to treading restrictions + /// and calling in a sync fashion on the UI thread was problematic. + /// + private Point browserScreenLocation; + /// /// A flag that indicates whether or not the designer is active /// NOTE: Needs to be static for OnApplicationExit @@ -601,15 +610,18 @@ bool IRenderWebBrowser.GetScreenPoint(int viewX, int viewY, out int screenX, out screenX = 0; screenY = 0; - var point = new Point(viewX, viewY); - - UiThreadRunSync(() => + //We manually claculate the screen point as calling PointToScreen can only be called on the UI thread + // in a sync fashion and it's easy for users to get themselves into a deadlock. + if(DpiScaleFactor > 1) + { + screenX = (int)(browserScreenLocation.X + (viewX * DpiScaleFactor)); + screenY = (int)(browserScreenLocation.Y + (viewY * DpiScaleFactor)); + } + else { - point = PointToScreen(point); - }); - - screenX = (int)point.X; - screenY = (int)point.Y; + screenX = (int)(browserScreenLocation.X + viewX); + screenY = (int)(browserScreenLocation.Y + viewY); + } return true; } @@ -1533,6 +1545,7 @@ private void PresentationSourceChangedHandler(object sender, SourceChangedEventA if(window != null) { window.StateChanged += WindowStateChanged; + window.LocationChanged += OnWindowLocationChanged; } } } @@ -1544,6 +1557,7 @@ private void PresentationSourceChangedHandler(object sender, SourceChangedEventA if (window != null) { window.StateChanged -= WindowStateChanged; + window.LocationChanged -= OnWindowLocationChanged; } } } @@ -1574,6 +1588,13 @@ private void WindowStateChanged(object sender, EventArgs e) } } + private void OnWindowLocationChanged(object sender, EventArgs e) + { + //We maintain a manual reference to the controls screen location + //(relative to top/left of the screen) + browserScreenLocation = PointToScreen(new Point()); + } + /// /// Removes the source hook. /// @@ -1720,6 +1741,9 @@ private void OnLoaded(object sender, RoutedEventArgs routedEventArgs) Dispatcher ); tooltipTimer.IsEnabled = false; + + //Initial value for screen location + browserScreenLocation = PointToScreen(new Point()); } ///