Closed f91kdash closed 2 months ago
可否给个复现方法,谢谢。
可否给个复现方法,谢谢。
做了多种尝试,xcode中无论是objc还是swift还是swiftui中使用webview都没有出现input框中无法输入中文的问题。但只要是rust,无论是用tauri还是通过objc crate创建的webview窗口就都会出现无法输入中文的问题,也不管是debug还是release。 编译出来的程序直接运行能正常输入。
可否给个可以无脑跟的步骤? 我甚至不知道从哪下手复现。你可以假设我已经安装了 Rust 工具链,但是具体要加什么 dependencies ,代码又是什么?
可否给个可以无脑跟的步骤? 我甚至不知道从哪下手复现。你可以假设我已经安装了 Rust 工具链,但是具体要加什么 dependencies ,代码又是什么?
随便做了个演示。 先在终端安装上cargo-bundle: cargo install cargo-bundle 然后下面是代码:
Cargo.toml
[package]
name = "demo"
version = "0.1.0"
edition = "2021"
[dependencies]
objc = "=0.2.7"
[package.metadata.bundle]
name = "demo"
identifier = "com.a.demo"
icon = ["icon/icon.png"]
version = "1.0.0"
short_description = "An example application."
main.rs
use objc::{class, declare::ClassDecl, msg_send, runtime::{Class, Object, Sel}, sel, sel_impl};
#[link(name = "Cocoa", kind = "framework")]
extern "C" {}
#[link(name = "WebKit", kind = "framework")]
extern "C" {}
type Id = *mut Object;
const NS_STRING_ENCODING_UTF8: usize = 4;
pub struct NSString(Id);
impl NSString {
#[inline]
pub fn from_str(s: &str) -> Self {
unsafe {
let ns_string: Id = msg_send![class!(NSString), alloc];
let ns_string: NSString = msg_send![ns_string,
initWithBytes: s.as_ptr()
length: s.len()
encoding: NS_STRING_ENCODING_UTF8];
let _: () = msg_send![ns_string.0, autorelease];
ns_string
}
}
#[inline]
pub fn len(&self) -> usize {
unsafe { msg_send![self.0, lengthOfBytesUsingEncoding: NS_STRING_ENCODING_UTF8] }
}
#[inline]
pub fn as_str(&self) -> &str {
unsafe {
let bytes: *const u8 = msg_send![self.0, UTF8String];
let bytes = std::slice::from_raw_parts(bytes, self.len());
std::str::from_utf8_unchecked(bytes)
}
}
}
#[derive(Clone, Copy)]
pub struct WebView {
pub inner_webview: Id,
pub content_controller: Id,
}
impl WebView {
pub fn new() -> Self {
unsafe {
let inner_webview = Class::get("InnerWebView").unwrap_or_else(|| {
let mut inner_webview = ClassDecl::new("InnerWebView", class!(WKWebView)).unwrap();
extern "C" fn will_open_menu(_this: &Object, _cmd: Sel, menu: Id, _event: Id) {
unsafe {
let _: () = msg_send![menu, removeAllItems];
}
}
inner_webview.add_method(
sel!(willOpenMenu:withEvent:),
will_open_menu as extern "C" fn(&Object, Sel, Id, Id),
);
return inner_webview.register();
});
let config: Id = msg_send![class!(WKWebViewConfiguration), new];
let content_controller: Id = msg_send![config, userContentController];
let preferences: Id = msg_send![config, preferences];
let yes_value: Id = msg_send![class!(NSNumber), numberWithBool: true];
let _: () = msg_send![preferences,
setValue: yes_value
forKey: NSString::from_str("allowFileAccessFromFileURLs")];
let _: () = msg_send![preferences,
setValue: yes_value
forKey: NSString::from_str("developerExtrasEnabled")];
let webview: Id = msg_send![inner_webview, alloc];
let webview: Id = msg_send![webview,
initWithFrame: (0_f64, 0_f64, 0_f64, 0_f64)
configuration: config];
let _: () = msg_send![webview, autorelease];
let _: () = msg_send![webview, setInspectable: true];
let _: () = msg_send![webview, setNavigationDelegate: webview];
let _: () = msg_send![webview, setUIDelegate: webview];
WebView { inner_webview: webview, content_controller }
}
}
pub fn load(&self, url: &str) {
unsafe {
match &url[0..6] {
"http:/" | "https:" => {
let ns_url: Id = msg_send![class!(NSURL), alloc];
let ns_url: Id = msg_send![ns_url, initWithString: NSString::from_str(url)];
let ns_req: Id = msg_send![class!(NSURLRequest), alloc];
let ns_req: Id = msg_send![ns_req, initWithURL: ns_url];
let _: () = msg_send![self.inner_webview, loadRequest: ns_req];
let _: () = msg_send![ns_req, release];
let _: () = msg_send![ns_url, release];
}
_ => {
let last_sep =
url.chars().count() - url.chars().rev().position(|c| c == '/').unwrap() - 1;
let path = &url[0..last_sep];
let ns_path: Id = msg_send![class!(NSURL), alloc];
let ns_path: Id = msg_send![ns_path,
initFileURLWithPath: NSString::from_str(path)
isDirectory: true];
let ns_url: Id = msg_send![class!(NSURL), alloc];
let ns_url: Id = msg_send![ns_url,
initFileURLWithPath: NSString::from_str(url)
isDirectory: false];
let ns_req: Id = msg_send![class!(NSURLRequest), alloc];
let ns_req: Id = msg_send![ns_req, initWithURL: ns_url];
let _: () = msg_send![self.inner_webview,
loadFileRequest: ns_req
allowingReadAccessToURL: ns_path];
let _: () = msg_send![ns_path, release];
let _: () = msg_send![ns_url, release];
let _: () = msg_send![ns_req, release];
}
}
}
}
}
fn main() {
unsafe {
let app: Id = msg_send![class!(NSApplication), sharedApplication];
let delegate = {
let mut delegate_decl = ClassDecl::new("AppDelegate", class!(NSObject)).unwrap();
extern "C" fn application_should_terminate_after_last_window_closed(
_this: &Object,
_cmd: objc::runtime::Sel,
_sender: Id,
) -> bool {
true
}
delegate_decl.add_method(
sel!(applicationShouldTerminateAfterLastWindowClosed:),
application_should_terminate_after_last_window_closed
as extern "C" fn(&Object, objc::runtime::Sel, Id) -> bool,
);
delegate_decl.register();
let delegate: Id = msg_send![class!(AppDelegate), alloc];
let delegate: Id = msg_send![delegate, init];
let _: () = msg_send![delegate, autorelease];
delegate
};
let _: () = msg_send![app, setDelegate: delegate];
let _: () = msg_send![app, setActivationPolicy: 0];
let ns_window: Id = msg_send![class!(NSWindow), alloc];
let ns_window: Id = msg_send![ns_window,
initWithContentRect: (0_f64, 0_f64, 1280_f64, 720_f64)
styleMask: 32783_usize // titled + closable + miniaturizable + fullScreen + fullSizeContentView
backing: 2_usize // buffered
defer: true];
let webview = WebView::new();
let _: () = msg_send![ns_window, setContentView: webview.inner_webview];
let _: () = msg_send![ns_window, makeFirstResponder: webview.inner_webview];
let _: () = msg_send![ns_window, makeKeyAndOrderFront: ns_window];
webview.load("https://www.bilibili.com/");
let _: () = msg_send![ns_window, makeKeyAndOrderFront: ns_window];
let running_app: Id = msg_send![class!(NSRunningApplication), currentApplication];
let _: () = msg_send![running_app, activateWithOptions: 2_u64];
let _: () = msg_send![app, run];
}
}
随便load一个页面,本地也行,http也行,只要有input框就能复现。 cargo run和build,都会出现无法输入中文的情况,但运行cargo bundle打包出来的app直接运行就能正常输入。无论debug还是release都一样。 我还测试了直接在终端运行safari,没有能复现,说明不是由终端启动应用导致。 系统14.6.1,鼠须管1.0.2 注:bundle的时候随便往项目下icon文件夹塞个icon.png就行。
感谢!复现了。
tauri(mac系用的是WKWebview)调试中input框输入不了中文,但编译后的app能正常输入。 mac自带输入法没有这个问题。
鼠须管版本是1.0.2,没有任何改动