[macOS] add support for title & url aware for ui

This commit is contained in:
Prome
2022-12-18 18:16:06 +08:00
parent cb5a4bc5c4
commit 8abba22d73
9 changed files with 82 additions and 2 deletions

View File

@@ -46,6 +46,17 @@ WebviewHandler* WebviewHandler::GetInstance() {
void WebviewHandler::OnTitleChange(CefRefPtr<CefBrowser> browser,
const CefString& title) {
//todo: title change
if(onTitleChangedCb) {
onTitleChangedCb(title);
}
}
void WebviewHandler::OnAddressChange(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& url) {
if(onUrlChangedCb) {
onUrlChangedCb(url);
}
}
void WebviewHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {

View File

@@ -17,6 +17,8 @@ public CefLoadHandler,
public CefRenderHandler{
public:
std::function<void(const void*, int32_t width, int32_t height)> onPaintCallback;
std::function<void(std::string url)> onUrlChangedCb;
std::function<void(std::string title)> onTitleChangedCb;
explicit WebviewHandler();
~WebviewHandler();
@@ -37,6 +39,9 @@ public:
// CefDisplayHandler methods:
virtual void OnTitleChange(CefRefPtr<CefBrowser> browser,
const CefString& title) override;
virtual void OnAddressChange(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& url) override;
// CefLifeSpanHandler methods:
virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;

View File

@@ -17,6 +17,7 @@ class MyApp extends StatefulWidget {
class _MyAppState extends State<MyApp> {
final _controller = WebViewController();
final _textController = TextEditingController();
String title = "";
@override
void initState() {
@@ -30,6 +31,16 @@ class _MyAppState extends State<MyApp> {
_textController.text = url;
await _controller.initialize();
await _controller.loadUrl(url);
_controller.setWebviewListener(WebviewEventsListener(
onTitleChanged: (t) {
setState(() {
title = t;
});
},
onUrlChanged: (url) {
_textController.text = url;
},
));
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
@@ -44,6 +55,10 @@ class _MyAppState extends State<MyApp> {
home: Scaffold(
body: Column(
children: [
SizedBox(
height: 20,
child: Text(title),
),
Row(
children: [
SizedBox(

View File

@@ -5,12 +5,15 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'webview_events_listener.dart';
const MethodChannel _pluginChannel = MethodChannel("webview_cef");
class WebViewController extends ValueNotifier<bool> {
late Completer<void> _creatingCompleter;
int _textureId = 0;
bool _isDisposed = false;
WebviewEventsListener? _listener;
Future<void> get ready => _creatingCompleter.future;
@@ -24,7 +27,7 @@ class WebViewController extends ValueNotifier<bool> {
_creatingCompleter = Completer<void>();
try {
_textureId = await _pluginChannel.invokeMethod<int>('init') ?? 0;
_pluginChannel.setMethodCallHandler(_methodCallhandler);
value = true;
_creatingCompleter.complete();
} on PlatformException catch (e) {
@@ -34,6 +37,23 @@ class WebViewController extends ValueNotifier<bool> {
return _creatingCompleter.future;
}
Future<void> _methodCallhandler(MethodCall call) async {
if (_listener == null) return;
switch (call.method) {
case "urlChanged":
_listener?.onUrlChanged?.call(call.arguments);
return;
case "titleChanged":
_listener?.onTitleChanged?.call(call.arguments);
return;
default:
}
}
setWebviewListener(WebviewEventsListener listener) {
_listener = listener;
}
@override
Future<void> dispose() async {
await _creatingCompleter.future;

View File

@@ -0,0 +1,9 @@
typedef TitleChangeCb = void Function(String title);
typedef UrlChangeCb = void Function(String url);
class WebviewEventsListener {
TitleChangeCb? onTitleChanged;
UrlChangeCb? onUrlChanged;
WebviewEventsListener({this.onTitleChanged, this.onUrlChanged});
}

View File

@@ -1 +1,2 @@
export 'src/webview.dart';
export 'src/webview.dart';
export 'src/webview_events_listener.dart';

View File

@@ -39,6 +39,8 @@ extern int64_t textureId;
+ (void) openDevTools;
+ (void) setMethodChannel: (FlutterMethodChannel*)channel;
@end
#endif /* CefWrapper_h */

View File

@@ -28,6 +28,8 @@ dispatch_semaphore_t lock = dispatch_semaphore_create(1);
int64_t textureId;
FlutterMethodChannel* f_channel;
@implementation CefWrapper
+ (void)init {
@@ -82,6 +84,16 @@ int64_t textureId;
dispatch_semaphore_signal(lock);
[tr textureFrameAvailable:textureId];
};
//url change cb
handler.get()->onUrlChangedCb = [](std::string url) {
[f_channel invokeMethod:@"urlChanged" arguments:[NSString stringWithCString:url.c_str() encoding:NSUTF8StringEncoding]];
};
//title change cb
handler.get()->onTitleChangedCb = [](std::string title) {
[f_channel invokeMethod:@"titleChanged" arguments:[NSString stringWithCString:title.c_str() encoding:NSUTF8StringEncoding]];
};
CefSettings settings;
settings.windowless_rendering_enabled = true;
settings.external_message_pump = true;
@@ -232,4 +244,8 @@ int64_t textureId;
return buf_temp;
}
+ (void)setMethodChannel: (FlutterMethodChannel*)channel {
f_channel = channel;
}
@end

View File

@@ -11,6 +11,7 @@
WebviewCefPlugin *instance = [[WebviewCefPlugin alloc] init];
[registrar addMethodCallDelegate:instance channel:channel];
[CefWrapper setMethodChannel:channel];
tr = registrar.textures;
}