0

In my FMX application I have a webpage that I'm rendering inside a TWebBrowser. The webpage has a simple <input>, but on Windows if I click the input it focuses and immediately unfocuses. After clicking a seemingly random number of times it stops unfocusing.

But if I AltTab to another application and back the problem happens again.

I have a very simple setup that reproduces the issue. I have an FMX application with just this code added:

procedure TForm1.FormCreate(Sender: TObject);
begin
  var browser := TWebBrowser.Create(Self);
  browser.WindowsEngine := TWindowsEngine.EdgeOnly;
  browser.Align := TAlignLayout.Client;
  browser.URL := 'http://localhost:8000/test.html';
  Self.AddObject(browser);
end;

I also have a test.html file with this content:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Test</title>
  </head>
  <body>
    <input type="text" name="test">
  </body>
</html>

I'm using Python to start a HTTP server so I can load test.html in the browser.

I've also added WebView2Loader.dll so .EdgeOnly works. Now if I use .IEOnly I don't have the issue, but I need to use .EdgeOnly for other stuff. It's not an option for me to use .IEOnly.

Anybody had this issue before?

Update: If I have a second screen connected to my laptop the issue does not happen.

3
  • Start by not having invalid HTML, so you can be sure the rendering engine's behavior is not caused by feeding it improperly. Commented Jun 16 at 14:24
  • @AmigoJack Modified the example. Doesn't change behavior. Commented Jun 16 at 14:47
  • Just tried out github.com/salvadordf/WebView4Delphi and it does work, but I don't know why. Currently investigating. Commented Jun 18 at 12:26

2 Answers 2

0

What about this ?

unit Unit13;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.WebBrowser,
  FMX.Platform,
  FMX.Platform.Win,
  Winapi.Windows,
  Winapi.Messages;

type
  TForm13 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    FBrowser: TWebBrowser;
    FWebViewRenderHandle: HWND;
    procedure BrowserDidFinishLoad(ASender: TObject);
    procedure WMParentNotify(var Message: TWMParentNotify); message WM_PARENTNOTIFY;
  public
  end;

var
  Form13: TForm13;

implementation

{$R *.fmx}

procedure TForm13.FormCreate(Sender: TObject);
begin
  FBrowser := TWebBrowser.Create(Self);
  FBrowser.Parent := Self;
  FBrowser.Align := TAlignLayout.Client;
  FBrowser.OnDidFinishLoad := BrowserDidFinishLoad;
  FBrowser.URL := 'http://localhost:8000/test.html';
end;

procedure TForm13.BrowserDidFinishLoad(ASender: TObject);
var
  WinService: IFMXWindowService;
  ParentHandle: HWND;
begin
  if (FBrowser <> nil) and (FWebViewRenderHandle = 0) then
  begin
    if TPlatformServices.Current.SupportsPlatformService(IFMXWindowService, IInterface(WinService)) then
    begin
      ParentHandle := WindowHandleToPlatform(Self.Handle).Wnd;
      if ParentHandle <> 0 then
      begin
        FWebViewRenderHandle := FindWindowEx(ParentHandle, 0, 'Chrome_RenderWidgetHostHWND', nil);
      end;
    end;
  end;
end;

procedure TForm13.WMParentNotify(var Message: TWMParentNotify);
begin
  if (Message.Event = WM_LBUTTONDOWN) and (FWebViewRenderHandle <> 0) then
  begin
    Winapi.Windows.SetFocus(FWebViewRenderHandle);
  end;
  inherited;
end;

end.

Sign up to request clarification or add additional context in comments.

1 Comment

Sadly not. WMParentNotify does not get called.
0

Seems to be a bug in FMX.WebBrowser.Win

I found that if I comment out SetFocus call in code below

FWebViewController.Add_GotFocus(
  Callback<ICoreWebView2, IUnknown>
    .CreateAs<ICoreWebView2FocusChangedEventHandler>(
      function(const WebView: ICoreWebView2; const Args: IUnknown): HResult; stdcall
      begin
        Result := S_OK;
        FWebViewFocusEventActive := True;
        SetFocus;
        FWebViewFocusEventActive := False;
      end
    ),
    FGotFocusToken);

it works.

SetFocus looks like this

procedure TWinPresentation.SetFocus;
begin
  Winapi.Windows.SetFocus(Handle);
end;

Compared to vcl version in VCL.Edge which does this

FWebViewController.Add_GotFocus(
  Callback<ICoreWebView2, IUnknown>
    .CreateAs<ICoreWebView2FocusChangedEventHandler>(
      function(const WebView: ICoreWebView2; const Args: IUnknown): HResult; stdcall
      begin
        Result := S_OK;
        FWebViewFocusEventActive := True;
        DoEnter;
        FWebViewFocusEventActive := False;
      end
    ), FGotFocusToken);
procedure TCustomEdgeBrowser.DoEnter;
begin
  inherited;
  if not FWebViewFocusEventActive and (FWebViewController <> nil) then
    ProcessHResult(
     WebViewController.MoveFocus(COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC));
end;

As you can see vcl version uses FWebViewFocusEventActive to skip changing focus on gotfocus event handler call but fmx version does set focus. So I think they wrongly copied vcl behavior here.

I'll make a bug report for this.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.