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.
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.