Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WPF: Add support for back and forward mouse buttons #2133

Closed
merceyz opened this issue Aug 31, 2017 · 11 comments
Closed

WPF: Add support for back and forward mouse buttons #2133

merceyz opened this issue Aug 31, 2017 · 11 comments
Labels
enhancement wpf WPF Implementation
Milestone

Comments

@merceyz
Copy link
Member

merceyz commented Aug 31, 2017

The WPF browser currently ignores XButton1 and XButton2.
These are used to navigate forward and backwards in Chrome, and should probably do so in CefSharp as well

// Cef currently only supports Left, Middle and Right button presses.
if (e.ChangedButton > MouseButton.Right)
{
return;
}

@merceyz merceyz added enhancement wpf WPF Implementation labels Aug 31, 2017
@merceyz merceyz added this to the 59.0.0 milestone Aug 31, 2017
@amaitland amaitland modified the milestones: 59.0.0, 62.0.0 Dec 13, 2017
@frederikstonge
Copy link

Could it be possible to disable this feature? Add a boolean to disable these buttons or make the method overriable.

@fvanheeswijk
Copy link

It would be appreciated if this feature could be enabled/disabled at runtime, as most of the times this behaviour is wanted but sometimes it is not.

@amaitland
Copy link
Member

You can already override the behavior, just inherit from ChromiumWebBrowser, override the two methods for mouse up/down and mark them as handled.

@fvanheeswijk
Copy link

@amaitland That should work indeed, thanks :) Though that does mean that I need to duplicate browser.GetHost().SendMouseClickEvent((int)point.X, (int)point.Y, (MouseButtonType)e.ChangedButton, mouseUp, e.ClickCount, modifiers);...

In short, if you change some things in private void OnMouseButton(MouseButtonEventArgs e) in the future, then I'll be missing those changes, I'm not sure if that is the best way to go, but for now it solves the issue.

@amaitland
Copy link
Member

How about setting the eventargs as handled and call the base method? Shouldn't need to duplicate anything

@fvanheeswijk
Copy link

That means though that private void OnMouseButton(MouseButtonEventArgs e) will not execute anything anymore, right? As the guard is !e.Handled && browser != null. And I just notice that in protected override void OnMouseDown(MouseButtonEventArgs e) I need to duplicate the Focus() call too.

To clarify: I still want (most) of the original behavior of OnMouseUp and OnMouseDown, I just don't want the back/forward navigation using mouse buttons.

@amaitland
Copy link
Member

To clarify: I still want (most) of the original behavior of OnMouseUp and OnMouseDown, I just don't want the back/forward navigation using mouse buttons.

That was perfectly clear.

And I just notice that in protected override void OnMouseDown(MouseButtonEventArgs e) I need to duplicate the Focus() call too.

For what reason?

CefSharp is build with GitLink, you can step into the source https://github.com/GitTools/GitLink

@fvanheeswijk
Copy link

fvanheeswijk commented Jul 26, 2018

I'll add the code of what I have thought of, hopefully you can see where I went wrong with this. I don't intend to use this in production as it is way too hacky. (I also haven't tested this code yet)

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Xaml;
using System.Windows.Controls;
using System.Windows.Input;

using CefSharp;
using CefSharp.Wpf;
using CefSharp.Wpf.Internals;

namespace Redacted
{
    public class CustomChromiumWebBrowser : ChromiumWebBrowser
    {
        public bool IgnoreForwardBackMouseNavigation { get; private set; }

        protected override void OnMouseDown(MouseButtonEventArgs e)
        {
            if (IgnoreForwardBackMouseNavigation)
            {
                Focus();
                OnMouseButton(e);

                CallGrandBaseMethod("OnMouseDown", e);
            }
            else
            {
                base.OnMouseDown(e);
            }
        }

        protected override void OnMouseUp(MouseButtonEventArgs e)
        {
            if (IgnoreForwardBackMouseNavigation)
            {
                OnMouseButton(e);

                CallGrandBaseMethod("OnMouseUp", e);
            }
            else
            {
                base.OnMouseUp(e);
            }
        }

        private void OnMouseButton(MouseButtonEventArgs e)
        {
            // implementation copied from https://github.com/cefsharp/CefSharp/blob/cefsharp/63/CefSharp.Wpf/ChromiumWebBrowser.cs#L2123
            // we do not implement the back/forward mouse button functionality (via XButton1/XButton2)

            var browser = GetBrowser();

            if (!e.Handled && browser != null)
            {
                var modifiers = e.GetModifiers();
                var mouseUp = (e.ButtonState == MouseButtonState.Released);
                var point = e.GetPosition(this);

                browser.GetHost().SendMouseClickEvent((int)point.X, (int)point.Y, (MouseButtonType)e.ChangedButton, mouseUp, e.ClickCount, modifiers);

                e.Handled = true;
            }
        }

        private void CallGrandBaseMethod(string methodName, MouseButtonEventArgs e)
        {
            var pointer = typeof(ContentControl).GetMethod(methodName).MethodHandle.GetFunctionPointer();
            var grandBaseMethod = (Action<MouseButtonEventArgs>)Activator.CreateInstance(typeof(Action<MouseButtonEventArgs>, this, pointer);
            grandBaseMethod(e);
        }
    }
}

I could have gotten it to work in a reasonably nice way if base.base.method() was allowed, but I understand the reasons of why it is not allowed in C#. If private void OnMouseButton(MouseButtonEventArgs e) was protected then it would fix (most) of the issues too in this case.

@amaitland
Copy link
Member

You appear to be overthinking things, try.

protected override void OnMouseDown(MouseButtonEventArgs e)
{
	if (e.ChangedButton == MouseButton.XButton1 || e.ChangedButton == MouseButton.XButton1)
	{
		e.Handled = true;
	}	

	base.OnMouseDown(e);
}

@fvanheeswijk
Copy link

That actually seems to be the solution I was looking for :) Thanks a lot, it is simple and effective.

@MelvilQ
Copy link

MelvilQ commented May 25, 2022

This is what we had to do to prevent navigation:

public class CustomChromiumWebBrowser : ChromiumWebBrowser
{
	protected override void OnMouseDown(MouseButtonEventArgs e)
	{
		if (e.ChangedButton == MouseButton.XButton1 || e.ChangedButton == MouseButton.XButton2)
		{
			e.Handled = true;
		}

		base.OnMouseDown(e);
	}

	protected override void OnMouseUp(MouseButtonEventArgs e)
	{
		if (e.ChangedButton == MouseButton.XButton1 || e.ChangedButton == MouseButton.XButton2)
		{
			e.Handled = true;
		}

		base.OnMouseUp(e);
	}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement wpf WPF Implementation
Projects
None yet
Development

No branches or pull requests

5 participants