Skip to content

Commit

Permalink
WPF - Fixed Html Dropdown positioning when near bottom of screen (Cle…
Browse files Browse the repository at this point in the history
…anup) (cefsharp#4759)

* WPF - Popup Mouse Transform

- Refactor and performance improvements
- WPF Example - Enable popup transform by default

Issue cefsharp#2820
  • Loading branch information
amaitland authored Mar 15, 2024
1 parent d606945 commit b26cb07
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 78 deletions.
3 changes: 3 additions & 0 deletions CefSharp.Wpf.Example/Views/BrowserTabView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using CefSharp.Fluent;
using CefSharp.Wpf.Example.Handlers;
using CefSharp.Wpf.Example.ViewModels;
using CefSharp.Wpf.Experimental;
using CefSharp.Wpf.Experimental.Accessibility;

namespace CefSharp.Wpf.Example.Views
Expand All @@ -31,6 +32,8 @@ public BrowserTabView()

DataContextChanged += OnDataContextChanged;

browser.UsePopupMouseTransform();

//browser.BrowserSettings.BackgroundColor = Cef.ColorSetARGB(0, 255, 255, 255);

//Please remove the comments below to use the Experimental WpfImeKeyboardHandler.
Expand Down
39 changes: 15 additions & 24 deletions CefSharp.Wpf/ChromiumWebBrowser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,6 @@ public partial class ChromiumWebBrowser : Control, IRenderWebBrowser, IWpfWebBro
/// </summary>
private static bool DesignMode;

/// <summary>
/// The class that coordinates the positioning of the dropdown if wanted.
/// </summary>
private IMouseAdjustor mouseAdjustor;

// https://github.com/chromiumembedded/cef/issues/3427
private bool resizeHackIgnoreOnPaint;
private Structs.Size? resizeHackSize;
Expand All @@ -155,6 +150,11 @@ public partial class ChromiumWebBrowser : Control, IRenderWebBrowser, IWpfWebBro
/// </summary>
private bool initialFocus;

/// <summary>
/// The class that coordinates the positioning of the dropdown if wanted.
/// </summary>
internal IMousePositionTransform MousePositionTransform { get; set; }

/// <summary>
/// When enabled the browser will resize by 1px when it becomes visible to workaround
/// the upstream issue
Expand Down Expand Up @@ -489,14 +489,6 @@ public ChromiumWebBrowser()
{
NoInliningConstructor();
}

bool adjust = true;

if (adjust)
this.mouseAdjustor = new MouseAdjustor();

else
this.mouseAdjustor = new NoMouseAdjustor();
}

/// <summary>
Expand Down Expand Up @@ -626,6 +618,7 @@ private void NoInliningConstructor()
PresentationSource.AddSourceChangedHandler(this, PresentationSourceChangedHandler);

MenuHandler = new ContextMenuHandler();
MousePositionTransform = new NoOpMousePositionTransform();

UseLayoutRounding = true;
}
Expand Down Expand Up @@ -1053,7 +1046,7 @@ protected virtual void OnPopupShow(bool isOpen)
UiThreadRunAsync(() =>
{
popupImage.Visibility = isOpen ? Visibility.Visible : Visibility.Hidden;
mouseAdjustor.OnPopupShow(isOpen);
MousePositionTransform.OnPopupShow(isOpen);
});
}

Expand Down Expand Up @@ -2125,7 +2118,7 @@ private void SetPopupSizeAndPositionImpl(Rect rect)
popupImage.Width = rect.Width;
popupImage.Height = rect.Height;

Point point = this.mouseAdjustor.UpdatePopupSizeAndPosition(rect, this.viewRect);
var point = MousePositionTransform.UpdatePopupSizeAndPosition(rect, viewRect);

Canvas.SetLeft(popupImage, point.X);
Canvas.SetTop(popupImage, point.Y);
Expand Down Expand Up @@ -2295,8 +2288,8 @@ protected override void OnMouseMove(MouseEventArgs e)
var point = e.GetPosition(this);
var modifiers = e.GetModifiers();

var adjustedPoint = mouseAdjustor.GetAdjustedMouseCoords(point);
browser.GetHost().SendMouseMoveEvent(adjustedPoint.X, adjustedPoint.Y, false, modifiers);
MousePositionTransform.TransformMousePoint(ref point);
browser.GetHost().SendMouseMoveEvent((int)point.X, (int)point.Y, false, modifiers);
}

base.OnMouseMove(e);
Expand All @@ -2313,11 +2306,11 @@ protected override void OnMouseWheel(MouseWheelEventArgs e)
var point = e.GetPosition(this);
var modifiers = e.GetModifiers();
var isShiftKeyDown = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift);
var adjustedPoint = mouseAdjustor.GetAdjustedMouseCoords(point);
MousePositionTransform.TransformMousePoint(ref point);

browser.SendMouseWheelEvent(
adjustedPoint.X,
adjustedPoint.Y,
(int)point.X,
(int)point.Y,
deltaX: isShiftKeyDown ? e.Delta : 0,
deltaY: !isShiftKeyDown ? e.Delta : 0,
modifiers: modifiers);
Expand Down Expand Up @@ -2467,11 +2460,9 @@ private void OnMouseButton(MouseButtonEventArgs e)
{
clickCount = 1;
}


var adjustedPoint = mouseAdjustor.GetAdjustedMouseCoords(point);
browser.GetHost().SendMouseClickEvent(adjustedPoint.X, adjustedPoint.Y, (MouseButtonType)e.ChangedButton, mouseUp, clickCount, modifiers);
// browser.GetHost().SendMouseClickEvent(mouseTeleport.originalRect.X + mouseTeleport.originalRect.Width, (int)point.Y, (MouseButtonType)e.ChangedButton, mouseUp, clickCount, modifiers);
MousePositionTransform.TransformMousePoint(ref point);
browser.GetHost().SendMouseClickEvent((int)point.X, (int)point.Y, (MouseButtonType)e.ChangedButton, mouseUp, clickCount, modifiers);
}

e.Handled = true;
Expand Down
12 changes: 12 additions & 0 deletions CefSharp.Wpf/Experimental/ExperimentalExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using CefSharp.Wpf.Internals;

namespace CefSharp.Wpf.Experimental
{
public static class ExperimentalExtensions
{
public static void UsePopupMouseTransform(this ChromiumWebBrowser chromiumWebBrowser)
{
chromiumWebBrowser.MousePositionTransform = new MousePositionTransform();
}
}
}
15 changes: 0 additions & 15 deletions CefSharp.Wpf/IMouseAdjustor.cs

This file was deleted.

14 changes: 14 additions & 0 deletions CefSharp.Wpf/Internals/IMousePositionTransform.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using CefSharp.Structs;

namespace CefSharp.Wpf.Internals
{
/// <summary>
/// Implement this interface to control transform the mouse position
/// </summary>
public interface IMousePositionTransform
{
System.Windows.Point UpdatePopupSizeAndPosition(Rect originalRect, Rect viewRect);
void OnPopupShow(bool isOpen);
void TransformMousePoint(ref System.Windows.Point point);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,7 @@

namespace CefSharp.Wpf.Internals
{
public class NoMouseAdjustor : IMouseAdjustor
{
public virtual void Dispose()
{
}

public System.Windows.Point UpdatePopupSizeAndPosition(Rect originalRect, Rect viewRect)
{
return new System.Windows.Point(originalRect.X, originalRect.Y);
}

public void OnPopupShow(bool isOpen)
{
}

public Point GetAdjustedMouseCoords(System.Windows.Point point)
{
return new Point((int)point.X, (int)point.Y);
}
}

public class MouseAdjustor : IMouseAdjustor
public sealed class MousePositionTransform : IMousePositionTransform
{
/// <summary>
/// The x-offset.
Expand All @@ -50,20 +29,13 @@ public class MouseAdjustor : IMouseAdjustor
/// </summary>
private bool isOpen;

/// <summary>
/// This method is required for the interface.
/// </summary>
public virtual void Dispose()
{
}

/// <summary>
/// Updates the size and the position of the popup.
/// </summary>
/// <param name="originalRect"></param>
/// <param name="viewRect"></param>
/// <returns>The adjusted point.</returns>
public System.Windows.Point UpdatePopupSizeAndPosition(Rect originalRect, Rect viewRect)
System.Windows.Point IMousePositionTransform.UpdatePopupSizeAndPosition(Rect originalRect, Rect viewRect)
{
int x = originalRect.X,
prevX = originalRect.X,
Expand Down Expand Up @@ -124,7 +96,7 @@ public System.Windows.Point UpdatePopupSizeAndPosition(Rect originalRect, Rect v
/// Resets the offsets and original-rect.
/// <param name="isOpen">If the popup is open or not.</param>
/// </summary>
public void OnPopupShow(bool isOpen)
void IMousePositionTransform.OnPopupShow(bool isOpen)
{
if (!isOpen)
{
Expand All @@ -142,16 +114,14 @@ public void OnPopupShow(bool isOpen)
/// Adjusts the mouse-coordinates when the popup is visible.
/// </summary>
/// <param name="point">The original point.</param>
/// <returns>The adjusted point if needed, else the original point.</returns>
public Point GetAdjustedMouseCoords(System.Windows.Point point)
/// <returns>The transformed point if needed, else the original point.</returns>
void IMousePositionTransform.TransformMousePoint(ref System.Windows.Point point)
{
if (!this.isOpen)
return new Point((int)point.X, (int)point.Y);

if (!this.IsInsideOriginalRect(point) && IsInsideAdjustedRect(point))
return new Point((int)point.X + this.xOffset, (int)point.Y + this.yOffset);
if (!isOpen)
return;

return new Point((int)point.X, (int)point.Y);
if (!IsInsideOriginalRect(point) && IsInsideAdjustedRect(point))
point = new System.Windows.Point((int)point.X + this.xOffset, (int)point.Y + this.yOffset);
}

/// <summary>
Expand Down
21 changes: 21 additions & 0 deletions CefSharp.Wpf/Internals/NoOpMousePositionTransform.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using CefSharp.Structs;

namespace CefSharp.Wpf.Internals
{
public sealed class NoOpMousePositionTransform : IMousePositionTransform
{
System.Windows.Point IMousePositionTransform.UpdatePopupSizeAndPosition(Rect originalRect, Rect viewRect)
{
return new System.Windows.Point(originalRect.X, originalRect.Y);
}

void IMousePositionTransform.OnPopupShow(bool isOpen)
{
}

void IMousePositionTransform.TransformMousePoint(ref System.Windows.Point point)
{

}
}
}

0 comments on commit b26cb07

Please sign in to comment.