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

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

在这里插入图片描述

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 上,AWTK 和 webview 都是基于原生窗口的,而 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.rhkb.cn/news/473332.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

类与对象;

目录 一、认识类&#xff1b; 1、类的引入&#xff1b; 2、类的定义&#xff1b; 类的两种定义方式&#xff1a; 3、类的访问限定符及封装&#xff1b; 4、类的作用域&#xff1b; 5、类的实例化&#xff1b; 6、类对象模型&#xff1b; 计算类对象的大小&#xff1b; …

Ubuntu22.04LTS 部署前后端分离项目

一、安装mysql8.0 1. 安装mysql8.0 # 更新安装包管理工具 sudo apt-get update # 安装 mysql数据库&#xff0c;过程中的选项选择 y sudo apt-get install mysql-server # 启动mysql命令如下 &#xff08;停止mysql的命令为&#xff1a;sudo service mysql stop&#xff0…

使用 Ant Design Vue 自定渲染函数customRender实现单元格合并功能rowSpan

使用 Ant Design Vue 自定渲染函数customRender实现单元格合并功能rowSpan 背景 在使用Ant Design Vue 开发数据表格时&#xff0c;我们常常会遇到需要合并单元格的需求。 比如&#xff0c;某些字段的值可能会在多行中重复出现&#xff0c;而我们希望将这些重复的单元格合并为…

27.<Spring博客系统③(实现用户退出登录接口+发布博客+删除/编辑博客)>

PS&#xff1a;关于打印日志 1.建议在关键节点打印日志。 ①请求入口。 ②结果响应 2.在可能发生错误的节点打印日志 3.日志不是越多越好。因为打日志也会消耗性能。 日志也可以配置去除重复日志。 一、用户退出功能 判断用户退出。我们只需要在前端将token删掉就可以了。 由于…

[前端面试]javascript

js数据类型 简单数据类型 null undefined string number boolean bigint 任意精度的大整数 symbol 创建唯一且不变的值&#xff0c;常用来表示对象属性的唯一标识 复杂数据类型 object&#xff0c;数组&#xff0c;函数,正则,日期等 区别 存储区别 简单数据类型因为其大小固定…

uniapp自动注册机制:easycom

传统 Vue 项目中&#xff0c;我们需要注册、导入组件之后才能使用组件。 uniapp 框架提供了一种组件自动注册机制&#xff0c;只要你在 components 文件夹下新建的组件满足 /components/组件名/组件名.vue 的命名规范&#xff0c;就能直接使用。 注意&#xff1a;组件的文件夹…

人工智能与SEO优化中的关键词策略解析

内容概要 在当今数字化快速发展的时代&#xff0c;人工智能&#xff08;AI&#xff09;与搜索引擎优化&#xff08;SEO&#xff09;的结合正变得愈发重要。关键词策略是SEO优化的一项基础工作&#xff0c;它直接影响到网站的可见性和流量。通过运用智能算法&#xff0c;企业能…

【异常解决】Linux shell报错:-bash: [: ==: 期待一元表达式 解决方法

博主介绍&#xff1a;✌全网粉丝21W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…

卷径计算(基于卷径变化微分方程计算实时卷径)

这里本质是积分法计算实时卷径,PLC里如何实现数值积分器算法请参考下面文章链接: 博途PLC数值积分器(矩形积分和梯形积分法自由切换) 博途PLC数值积分器(矩形梯形积分自由切换)_博图 积分计算-CSDN博客文章浏览阅读505次。本文详细介绍了博途PLC的数值积分器功能,涵盖了矩…

【Mysql】Mysql的多表查询---多表联合查询(上)

1、介绍 多表查询就是同时查询两个或者两个以上的表&#xff0c;因为有的时候&#xff0c;用户在查看数据的时候&#xff0c;需要显示的数据来自多张表&#xff0c;多表查询有以下分类&#xff1a; &#xff08;1&#xff09;交叉连接查询&#xff08;产生笛卡尔积&#xff0…

Shell基础(4)

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团…

跨平台WPF框架Avalonia教程 十五

ListBox 列表框 列表框从元素源集合中显示多行元素&#xff0c;并允许选择单个或多个。 列表中的元素可以组合、绑定和模板化。 列表的高度会扩展以适应所有元素&#xff0c;除非特别设置&#xff08;使用高度属性&#xff09;&#xff0c;或由容器控件设置&#xff0c;例如…

有序数组的平方(leetcode 977)

一个数组&#xff0c;返回一个所有元素的平方之后依然是一个有序数组。&#xff08;数组中含负数&#xff09; 解法一&#xff1a;暴力解法 所有元素平方后再使用快速排序法重新排序&#xff0c;时间复杂度为O(nlogn)。 class Solution { public:vector<int> sortedSqu…

使用 Go 实现将任何网页转化为 PDF

在许多应用场景中&#xff0c;可能需要将网页内容转化为 PDF 格式&#xff0c;比如保存网页内容、生成报告、或者创建网站截图。使用 Go 编程语言&#xff0c;结合一些现有的库&#xff0c;可以非常方便地实现这一功能。本文将带你一步一步地介绍如何使用 Go 语言将任何网页转换…

ASP.NET 部署到IIS,访问其它服务器的共享文件 密码设定

asp.net 修改上面的 IIS需要在 配置文件 添加如下内容 》》》web.config <system.web><!--<identity impersonate"true"/>--><identity impersonate"true" userName"您的账号" password"您的密码" /><co…

基础IO2

文章目录 磁盘结构磁盘存储结构磁盘的逻辑结构引入文件系统理解文件系统inode 映射 data blocks文件名与inode的关系dentry树文件描述符与进程之间的关系 深刻理解软硬链接软链接硬链接 动静态库静态库1. 手动制作静态库2.调用静态库(1)安装到系统(2)自己指定查找路径(3)自己创…

计算机网络:运输层 —— TCP的流量控制

文章目录 TCP的流量控制TCP的流量控制方法滑动窗口机制持续计时器 TCP的流量控制 当 TCP 客户端持续发送大量数据时&#xff0c;应用程序可能正忙于其他任务&#xff0c;并不一定能够立刻取走数据&#xff0c;这会造成接收方接收缓存的溢出&#xff0c;导致数据丢失。 TCP 为应…

Flink_DataStreamAPI_执行环境

DataStreamAPI_执行环境 1创建执行环境1.1getExecutionEnvironment1.2createLocalEnvironment1.3createRemoteEnvironment 2执行模式&#xff08;Execution Mode&#xff09;3触发程序执行 Flink程序可以在各种上下文环境中运行&#xff1a;我们可以在本地JVM中执行程序&#x…

鸿蒙中如何实现图片拉伸效果

2024年10月22日&#xff0c;华为发布会上&#xff0c;推出鸿蒙5.0。现在加入恰逢时机&#xff0c;你&#xff0c;我皆是鸿蒙时代合伙人。无论为了学习技术&#xff0c;还是为了谋福利&#xff0c;在鸿蒙的浩瀚海洋中分到一杯羹。现在学习鸿蒙正当时。 一文了解鸿蒙中图片拉伸的…

Unity 2022 Nav Mesh 自动寻路入门

untiy 2022 window-PackageManager-AINavigation 安装 Install 2.创建一个空物体命名Nav&#xff0c;在其自身挂载 NavMeshSurface 然后点击bake 烘焙地形即可 3.创建palyer和怪物 怪物AI代码 using System.Collections; using System.Collections.Generic; using UnityEngi…