规避Electron中webview在touch模式下失焦后第一次点击无效的问题
问题最近在用Electron中使用webview时发现当激活touch模式后,如果鼠标先点击了webview以外的区域使得焦点不在webview中,再回到webview时第一次点击无效。在Electron的issue中搜了一下发现这竟然又是一个从第一个版本到现在一直存在的Bug。规避方案既然Electron没有提供可以解决这个问题的方法,那就只能想办法规避这种情况了。在webview的页面中增加对
问题
最近在用Electron中使用webview时发现当激活touch模式后,如果鼠标先点击了webview以外的区域使得焦点不在webview中,再回到webview时第一次点击无效。
在Electron的issue中搜了一下发现这竟然又是一个从第一个版本到现在一直存在的Bug。
规避方案
既然Electron没有提供可以解决这个问题的方法,那就只能想办法规避这种情况了。
在webview的页面中增加对touchstart、touchmove、touchend的监听后发现:
window.addEventListener('touchend', (e) => {console.log('touchend', e)})
window.addEventListener('touchmove', (e)=>{console.log('touchmove', e)})
window.addEventListener('touchstart',(e)=>{console.log('touchstart', e);})

页面只监听到了鼠标左键按下(touchstart),后续的鼠标移动和鼠标左键弹起都没有被响应。
这说明一定是由于什么原因导致后续事件被中断了,但是在这次touchstart之后,app中的焦点已经被定位在webview中,所以后续的鼠标操作不会再有问题。
因此我这里提供的规避这个问题的办法就是在每次重新点击webview时,再模拟产生一次鼠标按下的情况,让后续流程可以接上。
// 主进程main.js
const { ipcMain, webContents } = require('electron')
ipcMain.on('touchstart', (e, msg) => {
// 这里是通过title找到webview对应的webContent,我的示例中webview加载的文件名是test.html
const webContent = webContents.getAllWebContents().find(item => item.getTitle() === 'test.html')
if (webContent) {
// 向对应webview发送mouseDown(也就是touchstart)事件
webContent.sendInputEvent({
...msg,
type: 'mouseDown',
button: 'left',
clickCount: 1
});
} else {
console.log('error')
}
})
// 渲染进程test.html
const { ipcRenderer } = require('electron')
// 用来模拟焦点是否在当前页面上
let isFocus = false
setInterval(() => {
console.log('焦点已不在区域内')
isFocus = false
}, 10000)
window.addEventListener('touchstart',(e)=>{
console.log('touchstart', e);
// 当监听到touchstart时,判断如果之前焦点不在当前webview,那向主进程发送模拟鼠标按下事件的消息
if (!isFocus) {
isFocus = true
ipcRenderer.send('touchstart', {x: e.touches[0].clientX, y: e.touches[0].clientY})
}
})
修改后再次点击webview时发现:
控制台上打印了两次start,一次end。
第一次start时自动激活了webview的焦点,我们再手动触发一次start
第二次start也就是我们在主进程发送的mouseDown事件
打印的end是我们在松开鼠标时打印的内容。
touchmove也是可以的
不过由于会多一次start事件,因此如果业务中对start有额外的逻辑,需要做特殊处理。
另外在示例中是模拟了焦点标志位的变化,实际中需要在外层页面和webview中增加第一次被点击时通知主进程焦点转移的逻辑,再由主进程通知每个webContent当前焦点在哪。
目前想到的这种方法只是一种替代的方案,如果有其他更好的方法,烦请告知,感激不尽。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐

所有评论(0)