AWTK-WIDGET-WEB-VIEW 实现笔记 (1) - 难点

news/2024/11/21 0:32:18/

webview 提供了一个跨平台的 webview 库,其接口简单,提供的例子也直观易懂。但是把它集成到 AWTK 里,还是遇到一些难题,这里记录一下,供有需要的朋友参考。

在这里插入图片描述

AWTK__5">1. 作为 AWTK 控件

webview 提供的例子都是独立的程序,要把它集成到 AWTK 里面,就需要把它封装成一个 AWTK 控件。没有找到参考的例子,只能自己摸索。

所幸 webview_create 提供了一个参数 window,让我们可以把 webview 嵌入到一个已有的窗口里面,不幸的是,不能指定 webview 在窗口的位置和大小。

webview 始终会占据整个窗口,这就需要将这个窗口,作为子窗口嵌入到主窗口中。技术上是可行的,难点在于不同平台实现方法不同。

/*** Creates a new webview instance.** @param debug Enable developer tools if supported by the backend.* @param window Optional native window handle, i.e. @c GtkWindow pointer*        @c NSWindow pointer (Cocoa) or @c HWND (Win32). If non-null,*        the webview widget is embedded into the given window, and the*        caller is expected to assume responsibility for the window as*        well as application lifecycle. If the window handle is null,*        a new window is created and both the window and application*        lifecycle are managed by the webview instance.* @remark Win32: The function also accepts a pointer to @c HWND (Win32) in the*         window parameter for backward compatibility.* @remark Win32/WebView2: @c CoInitializeEx should be called with*         @c COINIT_APARTMENTTHREADED before attempting to call this function*         with an existing window. Omitting this step may cause WebView2*         initialization to fail.* @return @c NULL on failure. Creation can fail for various reasons such*         as when required runtime dependencies are missing or when window*         creation fails.* @retval WEBVIEW_ERROR_MISSING_DEPENDENCY*         May be returned if WebView2 is unavailable on Windows.*/
WEBVIEW_API webview_t webview_create(int debug, void *window);

2. 两个主循环

webview 有自己的主循环:

/*** Runs the main loop until it's terminated.** @param w The webview instance.*/
WEBVIEW_API webview_error_t webview_run(webview_t w);

AWTK 也有自己的主循环:

/*** @method tk_run* 进入 TK 事件主循环。* @alias run* @annotation ["static", "scriptable"]** @return {ret_t} 返回 RET_OK 表示成功,否则表示失败。*/
ret_t tk_run(void);

创建 webview 后,如果运行 webview 的主循环,就不能运行 AWTK 的主循环,反之亦然。

解决思路有几个:

    1. 两个线程,一个运行 webview 的主循环,一个运行 AWTK 的主循环。事实证明不行,两者都需要在 GUI 线程运行。
    1. webview 的主循环中,调用 AWTK 的主循环的 main_loop_step 函数。webview 提供了 webview_dispatch 用于注册回调函数,可以在回调函数中调用 AWTK 的 step 函数。但是发现 main_loop_step 里读不到窗口的输入事件,可能是 webview 的主循环把所有窗口的输入事件都处理了。
/*** Schedules a function to be invoked on the thread with the run/event loop.* Use this function e.g. to interact with the library or native handles.** @param w The webview instance.* @param fn The function to be invoked.* @param arg An optional argument passed along to the callback function.*/
WEBVIEW_API webview_error_t webview_dispatch(webview_t w,void (*fn)(webview_t w, void *arg),void *arg);
    1. AWTK 的主循环中,调用 webview 的主循环的 step 函数。但是 webview 没有提供这样的函数。
    1. 只调用 AWTK 的主循环,不管 webview 的主循环。虽然看起来有点不合理,但是实际上,在 Windows 和 MacOS 上 webview 都能正常工作,但是 Linux 上却不行。事后想来也是可以理解的,在 Windows 和 MacOS 上,AWTKwebview 都是基于原生窗口的,而 Linux 上,AWTK 基于 X11,webview 基于 GTK,两者的窗口系统不同,可能有冲突。

3. 打开新窗口的问题

在 Windows 下,将 webview 封装成 AWTK 的控件,并没有遇到太大的问题,但是点击某些链接时,webview 却打开一个新的窗口,这个窗口独立于 AWTK 窗口之外。

观察后发现,是因为这些链接的 target 属性是 _blank,webview 会打开一个新的窗口。

<a target="_blank" href="https://mall.jd.com/index-1000377260.html">ZLG 商城</a>

解决方法是,hook 所有的点击事件,如果点击的是一个链接,且 target 是 _blank,就阻止默认行为,改为在当前窗口打开。webview 提供 webview_init 函数,可以在创建 webview 时,初始化一些 js 代码,这里就可以用到。

static const char* s_hook_click ="window.addEventListener('load', function() {\n""  window.on_url_changed(window.location.href);\n""  const links = document.querySelectorAll('a[target=\"_blank\"]'); \n""  links.forEach(function(link) { \n""    link.addEventListener('click', function(event) { \n""      event.preventDefault(); \n""      window.location.href = link.href; \n""    }); \n""  }); \n""});\n";webview_init(w, s_hook_click);

后面会介绍不同的平台的实现方法。


http://www.ppmy.cn/news/1548616.html

相关文章

【AI图像生成网站Golang】雪花算法

AI图像生成网站 目录 一、项目介绍 二、雪花算法 三、JWT认证与令牌桶算法 四、项目架构 五、图床上传与图像生成API搭建 六、项目测试与调试(等待更新) 雪花算法 雪花算法 (Snowflake) 是一种高效、可扩展的分布式唯一ID生成算法&#xff0c;最早由 Twitter 开发&…

react 中 useReducer Hook 作用

一、状态管理的替代方案 1. 与 useState 对比 useState是最基本的状态管理钩子。useReducer提供了一种更可预测的状态管理方式。 2. 基本用法示例 例如&#xff1a;用于一个简单的计数器应用。 import React, { useReducer } from "react";const counterReducer…

第二十五章 TCP 客户端 服务器通信 - TCP 设备的 READ 命令

文章目录 第二十五章 TCP 客户端 服务器通信 - TCP 设备的 READ 命令TCP 设备的 READ 命令READ 修改 $ZA 和 $ZB$ZA 和 READ 命令 第二十五章 TCP 客户端 服务器通信 - TCP 设备的 READ 命令 TCP 设备的 READ 命令 从服务器或客户端发出 READ 命令以读取客户端或服务器设置的…

这个 AI 懂 Vue 吗?

作者&#xff1a;前端俱乐部 写在前面 最近海外的 AI 编辑器 Cursor 好像挺火的&#xff0c;与此同时&#xff0c;字节跳动也推出了豆包MarsCode编程助手&#xff0c;可以直接生成代码和极限编程。 豆包MarsCode AI 支持网页版编辑器&#xff0c;但我个人更喜欢让它和人气爆棚…

linux 中mysql查看慢日志

1、到mysql容器&#xff0c;先登录到数据库&#xff0c;查看是否开启 mysql -h 127.0.0.1 -uroot -p SHOW VARIABLES LIKE slow_query_log; 2、如果没有开启&#xff0c;需要先开启 set global slow_query_log ON; 3、查看慢日志文件 SHOW VARIABLES LIKE slow_query_log…

生成式人工智能(AIGC)在软件开发设计模式课程教学中的应用

一、引言 软件设计模式作为软件工程领域的核心组成部分&#xff0c;对于提升软件系统的质量和可维护性至关重要。然而&#xff0c;传统的软件设计模式课程教学方法面临着诸多挑战&#xff0c;例如教师准备教学案例的过程繁琐&#xff0c;学生理解和应用具体案例难度较大&#…

华为刷题笔记--题目索引

文章目录 更多关于刷题的内容欢迎订阅我的专栏华为刷题笔记简单题目 更多关于刷题的内容欢迎订阅我的专栏华为刷题笔记 该专栏题目包含两部分&#xff1a; 100 分值部分题目 200 分值部分题目 所有题目都会陆续更新&#xff0c;订阅防丢失 简单题目 –题目分值试卷1华为OD机…

使用SaaS化的Aurora应用快速搭建私人ChatGPT助手

使用SaaS化的Aurora应用快速搭建私人ChatGPT助手 简介&#xff1a; Aurora是一个带UI且免费的GPT私人聊天助手&#xff0c;可切换GPT-3.5&#xff0c;4&#xff0c;4o等常用版本。用户可通过部署Aurora&#xff0c;快速打造自己专属的AI助手。阿里云计算巢已将Aurora打包为SaaS…