提交 f042d052 编写于 作者: yanghye's avatar yanghye

Merge branch 'dev'

# Conflicts:
#	cef/browser-window-lcl.go
#	cef/cef-application-config.go
#	cef/cef-events-callback.go
#	cef/i18n/i18n.go
#	example/browser-ipc-on-emit/go-to-js/go-to-js.go
#	example/browser-ipc-on-emit/go-to-js/resources/go-to-js.html
#	example/browser-ipc-on-emit/js-to-go/js-to-go.go
#	example/dev-test/lcl-browser/lcl-browser.go
......@@ -117,4 +117,6 @@ rsrc
1048576000
/exe/app.ico
/resources/manifest.xml
/app_windows_amd64.syso
\ No newline at end of file
/app_windows_amd64.syso
*.zip
*.rar
\ No newline at end of file
......@@ -9,7 +9,7 @@ English
---
[![github](https://img.shields.io/github/last-commit/energye/energy/main.svg?logo=github&logoColor=green&label=commit)](https://github.com/energye/energy)
[![release](https://img.shields.io/github/v/release/energye/energy?logo=git&logoColor=green)](https://github.com/energye/energy/releases)
[![release](https://img.shields.io/github/v/release/energye/energy?logo=git&logoColor=green)](https://github.com/energye/energy/v2/releases)
[![license](https://img.shields.io/github/license/energye/energy.svg?logo=git&logoColor=red)](http://www.apache.org/licenses/LICENSE-2.0)
![repo](https://img.shields.io/github/repo-size/energye/energy.svg?logo=github&logoColor=green&label=repo-size)
......@@ -99,7 +99,7 @@ Energy is a framework developed by Golang based on CEF(Chromium Embedded Framewo
package main
import (
"github.com/energye/energy/cef"
"github.com/energye/energy/v2/cef"
)
func main() {
......
......@@ -10,7 +10,7 @@
---
[![github](https://img.shields.io/github/last-commit/energye/energy/main.svg?logo=github&logoColor=green&label=commit)](https://github.com/energye/energy)
[![release](https://img.shields.io/github/v/release/energye/energy?logo=git&logoColor=green)](https://github.com/energye/energy/releases)
[![release](https://img.shields.io/github/v/release/energye/energy?logo=git&logoColor=green)](https://github.com/energye/energy/v2/releases)
[![license](https://img.shields.io/github/license/energye/energy.svg?logo=git&logoColor=red)](http://www.apache.org/licenses/LICENSE-2.0)
![repo](https://img.shields.io/github/repo-size/energye/energy.svg?logo=github&logoColor=green&label=repo-size)
......@@ -96,7 +96,7 @@
package main
import (
"github.com/energye/energy/cef"
"github.com/energye/energy/v2/cef"
)
func main() {
......
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
// application event 默认事件实现
package cef
import (
"github.com/energye/energy/v2/cef/internal/ipc"
"github.com/energye/energy/v2/cef/internal/process"
"github.com/energye/energy/v2/consts"
)
// appOnContextCreated 创建应用上下文 - 默认实现
func appOnContextCreated(browser *ICefBrowser, frame *ICefFrame, context *ICefV8Context) {
process.Current.SetBrowserId(browser.Identifier()) // 当前进程 browserID
process.Current.SetFrameId(frame.Identifier()) // 当前进程 frameId
ipc.RenderChan().SetRealityChannel(browser.Identifier(), frame.Identifier()) // 设置并更新真实的通道ID
ipcRender.registerGoSyncReplayEvent() // render ipc
bindRender.registerContextEvent() // TODO render bind
ipcRender.makeIPC(context) // render ipc make
makeProcess(browser, frame, context) // process make
}
// appMainRunCallback 应用运行 - 默认实现
func appMainRunCallback() {
ipcBrowser.registerEvent() // browser ipc
// bindBrowser.registerFieldBindEvent() // TODO browser bind
}
// appWebKitInitialized - webkit - 默认实现
func appWebKitInitialized() {
// TODO VF 窗口还有问题
//bindRender.registerFieldBindResultEvent() // render webkit get binds
}
// renderProcessMessageReceived 渲染进程消息 - 默认实现
func renderProcessMessageReceived(browser *ICefBrowser, frame *ICefFrame, sourceProcess consts.CefProcessId, message *ICefProcessMessage) (result bool) {
if message.Name() == internalIPCJSExecuteGoEventReplay {
result = ipcRender.ipcJSExecuteGoEventMessageReply(browser, frame, sourceProcess, message)
} else if message.Name() == internalIPCGoExecuteJSEvent {
result = ipcRender.ipcGoExecuteJSEvent(browser, frame, sourceProcess, message)
}
return
}
// browserProcessMessageReceived 主进程消息 - 默认实现
func browserProcessMessageReceived(browser *ICefBrowser, frame *ICefFrame, message *ICefProcessMessage) (result bool) {
if message.Name() == internalIPCJSExecuteGoEvent {
result = ipcBrowser.jsExecuteGoMethodMessage(browser, frame, message)
}
return
}
此差异已折叠。
......@@ -8,11 +8,12 @@
//
//----------------------------------------
// 应用主线程异步回调
// 在应用主线程中执行(非主线程使用)异步&同步执行包裹函数
package cef
import (
"github.com/energye/energy/common/imports"
"github.com/energye/energy/v2/common/imports"
"github.com/energye/golcl/lcl/api/dllimports"
"math"
"sync"
......@@ -33,7 +34,7 @@ func applicationQueueAsyncCallProc(id uintptr) uintptr {
return 0
}
// 队列异步调用函数 id:事件id
// qacFn 队列异步调用函数 id:事件id
type qacFn func(id int)
type queueCall struct {
......@@ -45,18 +46,21 @@ type queueCall struct {
type queueAsyncCall struct {
id uintptr
calls sync.Map
lock sync.Mutex
}
// LCL UI
// QueueAsyncCall 仅LCL,在主进程中异步调用
//
// 1.在UI主进程中执行, 队列异步调用-适用大多场景(包括UI线程和非UI线程)
// 在UI主进程中执行, 异步执行
//
// 2.大多数非UI线程操作都需要使用该函数
// 非主进程的多线程操作可使用该函数包裹
//
// 3.在任何变更UI的操作都有可能导致UI线程不一至出现程序错误或程序崩溃, 可以尝试使用该回调函数解决.
// 在任何变更UI的操作都有可能因非主线程出现不一至, 而出现程序错误或程序崩溃, 可以尝试使用该回调函数解决.
//
// 4.在windows linux macos 可同时使用
// 提示: CEF事件或函数中不应使用该函数包裹
func QueueAsyncCall(fn qacFn) int {
qac.lock.Lock()
defer qac.lock.Unlock()
id := qac.set(&queueCall{
IsSync: false,
Fn: fn,
......@@ -65,15 +69,9 @@ func QueueAsyncCall(fn qacFn) int {
return int(id)
}
// LCL UI
//
// 1.在UI主进程中执行, 队列异步调用-适用大多场景(非UI线程)
//
// 2.大多数非UI线程操作都需要使用该函数
//
// 3.在任何变更UI的操作都有可能导致UI线程不一至出现程序错误或程序崩溃, 可以尝试使用该回调函数解决.
// QueueSyncCall 同 QueueAsyncCall
//
// 4.在windows linux macos 需要注意使用场景, 当非UI线程使用时正常执行, UI线程使用时会造成UI线程锁死, 这种情况建议使用 QueueAsyncCall 自己增加同步锁
// 同步执行 - 阻塞UI
func QueueSyncCall(fn qacFn) int {
qc := &queueCall{
IsSync: true,
......
......@@ -30,7 +30,7 @@ import (
//export doApplicationQueueAsyncCallEventProc
func doApplicationQueueAsyncCallEventProc(f unsafe.Pointer) unsafe.Pointer {
applicationQueueAsyncCallProc(uintptr(f))
return nullptr
return nil
}
var (
......
......@@ -9,33 +9,29 @@
//----------------------------------------
// energy application run
package cef
import (
"github.com/energye/energy/common"
"github.com/energye/energy/consts"
"github.com/energye/energy/ipc"
"github.com/energye/energy/logger"
"github.com/energye/energy/v2/cef/process"
"github.com/energye/energy/v2/common"
"github.com/energye/energy/v2/consts"
"github.com/energye/golcl/lcl"
"github.com/energye/golcl/lcl/api"
)
var (
//BrowserWindow 是基于LCL和VF窗口组件的浏览器主窗口
//
//可以对窗口的属性设置和事件监听,Chromium的配置和事件监听.
//
//该窗口是主窗体,因此初始化时必须第一个初始化完成,如果创建子窗口最好在 SetBrowserInitAfter 回调函数中创建
//
//VF窗口组件默认在Linux平台自动开启
//LCL窗口组件默认在Windows、MacOSX平台自动开启
BrowserWindow = &browser{
// 可以对窗口的属性设置和事件监听,Chromium的配置和事件监听.
// 该窗口是主窗体,因此初始化时必须第一个初始化完成,如果创建子窗口最好在 SetBrowserInitAfter 回调函数中创建
// VF 窗口组件默认在Linux平台
// LCL窗口组件默认在Windows、MacOSX平台
BrowserWindow = &browserWindow{
browserEvent: &BrowserEvent{},
Config: &browserConfig{
WindowProperty: NewWindowProperty(),
},
windowInfo: make(map[int32]IBrowserWindow),
windowSerial: 1, //默认1开始
windowInfo: make(map[int32]IBrowserWindow),
}
browserProcessStartAfterCallback browserProcessStartAfterCallbackFunc
)
......@@ -44,52 +40,50 @@ type browserProcessStartAfterCallbackFunc func(success bool)
// SetBrowserProcessStartAfterCallback 主进程启动之后回调函数
func SetBrowserProcessStartAfterCallback(callback browserProcessStartAfterCallbackFunc) {
if common.Args.IsMain() {
if process.Args.IsMain() {
if browserProcessStartAfterCallback == nil {
browserProcessStartAfterCallback = callback
}
}
}
// Run
// 运行应用
//
// 多进程方式,启动主进程然后启动子进程,在MacOS下,需要单独调用启动子进程函数,单进程只启动主进程
//
// 主进程启动成功之后,将创建主窗口 mainBrowserWindow 是一个默认的主窗口
//
// externalMessagePump和multiThreadedMessageLoop是false时启用 ViewsFrameworkBrowserWindow 窗口
//
// 在这里启动浏览器的主进程和子进程
func Run(cefApp *TCEFApplication) {
// Run 运行应用
// 在这里启动浏览器的主进程和子进程
func Run(app *TCEFApplication) {
defer func() {
logger.Debug("application process [", common.Args.ProcessType(), "] run end")
api.EnergyLibRelease()
}()
if common.IsDarwin() && !consts.SingleProcess && !common.Args.IsMain() {
// mac os 启动子进程
cefApp.StartSubProcess()
cefApp.Free()
//MacOSX 多进程时,需要调用StartSubProcess来启动子进程
if common.IsDarwin() && !app.SingleProcess() && !process.Args.IsMain() {
// 启动子进程
app.StartSubProcess()
app.Free()
} else {
//externalMessagePump 和 multiThreadedMessageLoop 为 false 时启用CEF views framework (ViewsFrameworkBrowserWindow) 窗口
consts.IsMessageLoop = !api.GoBool(cefApp.cfg.externalMessagePump) && !api.GoBool(cefApp.cfg.multiThreadedMessageLoop)
//externalMessagePump 和 multiThreadedMessageLoop 为 false 时, 启用 VF (ViewsFrameworkBrowserWindow) 窗口组件
emp := app.ExternalMessagePump()
mtml := app.MultiThreadedMessageLoop()
consts.IsMessageLoop = !emp && !mtml
if consts.IsMessageLoop {
BrowserWindow.appContextInitialized(cefApp)
// 启用VF窗口组件
BrowserWindow.appContextInitialized(app)
}
success := cefApp.StartMainProcess()
// 启动主进程
success := app.StartMainProcess()
// 主进程启动成功之后回调
if browserProcessStartAfterCallback != nil {
browserProcessStartAfterCallback(success)
}
if success {
internalBrowserIPCOnEventInit()
ipc.IPC.StartBrowserIPC()
bindGoToJS(nil, nil)
appMainRunCallback()
if consts.IsMessageLoop {
cefApp.RunMessageLoop()
// VF窗口消息轮询
app.RunMessageLoop()
} else {
// 创建LCL窗口组件
if BrowserWindow.mainBrowserWindow == nil {
BrowserWindow.mainBrowserWindow = &browserWindow{}
BrowserWindow.mainBrowserWindow = new(lclBrowserWindow)
}
// 运行主窗口
lcl.RunApp(&BrowserWindow.mainBrowserWindow)
}
}
......
......@@ -9,11 +9,13 @@
//----------------------------------------
// 辅助工具-开发者工具
package cef
import (
"fmt"
. "github.com/energye/energy/consts"
"github.com/energye/energy/v2/common/imports"
. "github.com/energye/energy/v2/consts"
"github.com/energye/golcl/lcl"
"github.com/energye/golcl/lcl/api"
"github.com/energye/golcl/lcl/types"
......@@ -28,70 +30,65 @@ func updateBrowserDevTools(browser *ICefBrowser, title string) {
if browserWinInfo.IsLCL() {
window := browserWinInfo.AsLCLBrowserWindow().BrowserWindow()
if window.getAuxTools() != nil && window.getAuxTools().devToolsWindow != nil {
QueueAsyncCall(func(id int) {
window.getAuxTools().devToolsWindow.SetTitle(fmt.Sprintf("%s - %s", dev_tools_name, browser.MainFrame().Url))
})
window.getAuxTools().devToolsWindow.SetTitle(fmt.Sprintf("%s - %s", dev_tools_name, browser.MainFrame().Url()))
}
}
}
}
func (m *ICefBrowser) createBrowserDevTools(browserWinInfo IBrowserWindow) {
if browserWinInfo.IsLCL() {
QueueAsyncCall(func(id int) {
window := browserWinInfo.AsLCLBrowserWindow().BrowserWindow()
window.createAuxTools()
if window.getAuxTools().devToolsWindow != nil {
dtw := window.getAuxTools().devToolsWindow.AsLCLBrowserWindow().BrowserWindow()
func (m *ICefBrowser) createBrowserDevTools(browserWindow IBrowserWindow) {
if browserWindow.IsLCL() {
window := browserWindow.AsLCLBrowserWindow().BrowserWindow()
window.createAuxTools()
if window.getAuxTools().devToolsWindow != nil {
dtw := window.getAuxTools().devToolsWindow.AsLCLBrowserWindow().BrowserWindow()
QueueAsyncCall(func(id int) {
if dtw.WindowState() == types.WsMinimized {
dtw.SetWindowState(types.WsNormal)
}
dtw.Show()
dtw.Active()
dtw.Focused()
return
}
wp := NewWindowProperty()
wp.Title = fmt.Sprintf("%s - %s", dev_tools_name, m.MainFrame().Url)
wp.WindowType = WT_DEV_TOOLS
wp.Url = m.MainFrame().Url
devToolsWindow := NewLCLBrowserWindow(nil, wp)
window.auxTools.devToolsWindow = devToolsWindow
devToolsWindow.SetWidth(800)
devToolsWindow.SetHeight(600)
devToolsWindow.SetOnClose(func(sender lcl.IObject, action *types.TCloseAction) bool {
if devToolsWindow.isClosing {
return false
}
*action = types.CaFree
return true
})
devToolsWindow.SetOnCloseQuery(func(sender lcl.IObject, canClose *bool) bool {
if devToolsWindow.isClosing {
return true
}
devToolsWindow.isClosing = true
BrowserWindow.removeWindowInfo(devToolsWindow.Id())
window.auxTools.devToolsWindow = nil
return
}
wp := NewWindowProperty()
wp.Url = m.MainFrame().Url()
wp.Title = fmt.Sprintf("%s - %s", dev_tools_name, m.MainFrame().Url())
wp.WindowType = WT_DEV_TOOLS
devToolsWindow := NewLCLBrowserWindow(nil, wp)
devToolsWindow.SetWidth(1024)
devToolsWindow.SetHeight(768)
window.auxTools.devToolsWindow = devToolsWindow
devToolsWindow.SetOnClose(func(sender lcl.IObject, action *types.TCloseAction) bool {
if devToolsWindow.isClosing {
return false
}
*action = types.CaFree
return true
})
devToolsWindow.SetOnCloseQuery(func(sender lcl.IObject, canClose *bool) bool {
if devToolsWindow.isClosing {
return true
})
devToolsWindow.EnableDefaultCloseEvent()
devToolsWindow.Show()
BrowserWindow.setOrIncNextWindowNum() //明确的生成下一个窗体序号
_CEFBrowser_ShowDevTools(devToolsWindow.chromium.Instance(), uintptr(m.Identifier()), devToolsWindow.windowParent.Instance(), api.PascalStr(dev_tools_name))
}
devToolsWindow.isClosing = true
window.auxTools.devToolsWindow = nil
return true
})
} else if browserWinInfo.IsViewsFramework() {
if application.cfg.remoteDebuggingPort > 1024 && application.cfg.remoteDebuggingPort < 65535 {
devToolsWindow.chromiumBrowser.CreateBrowser()
devToolsWindow.Show()
imports.Proc(internale_CEFBrowser_ShowDevTools).Call(m.Instance(), devToolsWindow.Chromium().Instance(), devToolsWindow.WindowParent().Instance(), api.PascalStr(dev_tools_name))
} else if browserWindow.IsViewsFramework() {
if application.RemoteDebuggingPort() > 1024 && application.RemoteDebuggingPort() < 65535 {
wp := NewWindowProperty()
wp.Url = fmt.Sprintf("http://127.0.0.1:%d", application.cfg.remoteDebuggingPort)
wp.Url = fmt.Sprintf("http://127.0.0.1:%d", application.RemoteDebuggingPort())
wp.Title = dev_tools_name
wp.IconFS = BrowserWindow.Config.IconFS
wp.Icon = BrowserWindow.Config.Icon
wp.WindowType = WT_DEV_TOOLS
devToolsWindow := NewViewsFrameworkBrowserWindow(nil, wp, BrowserWindow.MainWindow().AsViewsFrameworkBrowserWindow().Component())
devToolsWindow.ResetWindowPropertyForEvent()
devToolsWindow.SetWindowType(WT_DEV_TOOLS)
BrowserWindow.setOrIncNextWindowNum() //明确的生成下一个窗口序号
devToolsWindow.windowComponent.CreateTopLevelWindow()
devToolsWindow.CreateTopLevelWindow()
}
}
}
......@@ -9,13 +9,14 @@
//----------------------------------------
// 辅助工具-显示网页源代码
package cef
import (
"fmt"
"github.com/energye/energy/common"
"github.com/energye/energy/common/assetserve"
. "github.com/energye/energy/consts"
"github.com/energye/energy/v2/common"
. "github.com/energye/energy/v2/consts"
"github.com/energye/energy/v2/pkgs/assetserve"
"github.com/energye/golcl/lcl"
)
......@@ -23,29 +24,30 @@ const (
view_source_name = "view-source"
)
func (m *ICefBrowser) createBrowserViewSource(frame *ICefFrame) {
func (m *ICefBrowser) createBrowserViewSource() {
if currentWindowInfo := BrowserWindow.GetWindowInfo(m.Identifier()); currentWindowInfo != nil {
var frame = m.MainFrame()
if currentWindowInfo.IsLCL() {
var viewSourceUrl = fmt.Sprintf("view-source:%s", frame.Url)
QueueAsyncCall(func(id int) {
wp := NewWindowProperty()
wp.Url = viewSourceUrl
wp.Title = fmt.Sprintf("%s - %s", view_source_name, frame.Url)
wp.WindowType = WT_VIEW_SOURCE
viewSourceWindow := NewLCLBrowserWindow(nil, wp)
viewSourceWindow.SetWidth(800)
viewSourceWindow.SetHeight(600)
if common.IsDarwin() {
viewSourceWindow.Chromium().SetOnAfterCreated(func(sender lcl.IObject, browser *ICefBrowser) {
viewSourceWindow.Chromium().LoadUrl(viewSourceUrl)
})
}
if assetserve.AssetsServerHeaderKeyValue != "" {
viewSourceWindow.Chromium().SetOnBeforeResourceLoad(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest, callback *ICefCallback, result *TCefReturnValue) {
request.SetHeaderByName(assetserve.AssetsServerHeaderKeyName, assetserve.AssetsServerHeaderKeyValue, true)
})
}
viewSourceWindow.EnableDefaultCloseEvent()
var viewSourceUrl = fmt.Sprintf("view-source:%s", frame.Url())
wp := NewWindowProperty()
wp.Url = viewSourceUrl
wp.Title = fmt.Sprintf("%s - %s", view_source_name, frame.Url())
wp.WindowType = WT_VIEW_SOURCE
viewSourceWindow := NewLCLBrowserWindow(nil, wp)
viewSourceWindow.SetWidth(800)
viewSourceWindow.SetHeight(600)
if common.IsDarwin() {
viewSourceWindow.Chromium().SetOnAfterCreated(func(sender lcl.IObject, browser *ICefBrowser) {
viewSourceWindow.Chromium().LoadUrl(viewSourceUrl)
})
}
if assetserve.AssetsServerHeaderKeyValue != "" {
viewSourceWindow.Chromium().SetOnBeforeResourceLoad(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest, callback *ICefCallback, result *TCefReturnValue) {
request.SetHeaderByName(assetserve.AssetsServerHeaderKeyName, assetserve.AssetsServerHeaderKeyValue, true)
})
}
viewSourceWindow.EnableDefaultCloseEvent()
QueueAsyncCall(func(id int) { //main thread run
viewSourceWindow.Show()
})
} else if currentWindowInfo.IsViewsFramework() {
......
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
package cef
import (
"github.com/energye/energy/v2/common/imports"
"unsafe"
)
type ICefBaseRefCounted interface {
Instance() uintptr
IsValid() bool
}
func NewBaseRefCounted(instance uintptr) *TCefBaseRefCounted {
return &TCefBaseRefCounted{instance: unsafe.Pointer(instance)}
}
// Wrap 指针引用包裹
func (m *TCefBaseRefCounted) Wrap(data uintptr) unsafe.Pointer {
var result uintptr
imports.Proc(internale_CefBaseRefCounted_Wrap).Call(data, uintptr(unsafe.Pointer(&result)))
return unsafe.Pointer(result)
}
// Free 释放底层指针
func (m *TCefBaseRefCounted) Free(data uintptr) {
imports.Proc(internale_CefBaseRefCounted_Free).Call(uintptr(unsafe.Pointer(&data)))
m.instance = nil
}
// Instance 实例
func (m *TCefBaseRefCounted) Instance() uintptr {
if m == nil {
return 0
}
return uintptr(m.instance)
}
func (m *TCefBaseRefCounted) IsValid() bool {
if m == nil || m.instance == nil {
return false
}
return m.instance != nil
}
......@@ -9,6 +9,7 @@
//----------------------------------------
// CEF Window Parent 父组件
package cef
import (
......@@ -16,7 +17,7 @@ import (
"unsafe"
)
// WindowParent和WindowLinkedParent父结构体
// BaseWinControl TCEFWindowParent 和 TCEFLinkedWindowParent 父结构体
type BaseWinControl struct {
lcl.IWinControl
instance unsafe.Pointer
......@@ -24,7 +25,7 @@ type BaseWinControl struct {
// IsValid 是否有效
func (m *BaseWinControl) IsValid() bool {
return m.instance != nullptr
return m.instance != nil
}
// Instance 当前实例
......
......@@ -9,31 +9,31 @@
//----------------------------------------
// Browser Window 配置
package cef
import (
"github.com/energye/energy/common"
"github.com/energye/energy/v2/cef/process"
)
type browserWindowOnEventCallback func(event *BrowserEvent, window IBrowserWindow)
type browserWindowAfterOnEventCallback func(window IBrowserWindow)
// 创建主窗口指定的一些快捷配置属性
type browserConfig struct {
WindowProperty
chromiumConfig *tCefChromiumConfig //主窗体浏览器配置
browserWindowOnEventCallback browserWindowOnEventCallback //主窗口初始化回调 - 基于LCL窗口
browserWindowAfterOnEventCallback browserWindowAfterOnEventCallback //主窗口初始化之后回调
chromiumConfig *tCefChromiumConfig //主窗体浏览器配置
browserWindowOnEventCallback browserWindowOnEventCallback //主窗口初始化回调
}
// 设置chromium配置
// SetChromiumConfig 设置chromium配置
func (m *browserConfig) SetChromiumConfig(chromiumConfig *tCefChromiumConfig) {
if chromiumConfig != nil && common.Args.IsMain() {
if chromiumConfig != nil && process.Args.IsMain() {
m.chromiumConfig = chromiumConfig
}
}
// 获取/创建 CEF Chromium Config
// ChromiumConfig 扩展配置
// 获取/创建 CEF Chromium Config
func (m *browserConfig) ChromiumConfig() *tCefChromiumConfig {
if m.chromiumConfig == nil {
m.chromiumConfig = NewChromiumConfig()
......@@ -42,17 +42,9 @@ func (m *browserConfig) ChromiumConfig() *tCefChromiumConfig {
}
// 主窗口初始化回调
//
// 该回调函数和基于CEF窗口回调是互斥的,默认情况只有一个会被回调
// 创建主窗口后,显示之前执行
func (m *browserConfig) setBrowserWindowInitOnEvent(fn browserWindowOnEventCallback) {
if fn != nil && common.Args.IsMain() {
if fn != nil && process.Args.IsMain() {
m.browserWindowOnEventCallback = fn
}
}
// 主窗口初始化回调 - 基于LCL窗口
func (m *browserConfig) setBrowserWindowInitAfterOnEvent(fn browserWindowAfterOnEventCallback) {
if fn != nil && common.Args.IsMain() {
m.browserWindowAfterOnEventCallback = fn
}
}
......@@ -8,13 +8,13 @@
//
//----------------------------------------
// VF 窗口组件,BrowserView
// VF 窗口组件 BrowserView
package cef
import (
"github.com/energye/energy/common/imports"
"github.com/energye/energy/consts"
"github.com/energye/energy/logger"
"github.com/energye/energy/v2/common/imports"
"github.com/energye/energy/v2/consts"
"github.com/energye/golcl/lcl"
"github.com/energye/golcl/lcl/api"
"unsafe"
......@@ -28,35 +28,19 @@ type TCEFBrowserViewComponent struct {
// NewBrowserViewComponent
func NewBrowserViewComponent(AOwner lcl.IComponent) *TCEFBrowserViewComponent {
r1, _, _ := imports.Proc(internale_CEFBrowserViewComponent_Create).Call(lcl.CheckPtr(AOwner))
return &TCEFBrowserViewComponent{
instance: unsafe.Pointer(r1),
}
var result uintptr
imports.Proc(internale_CEFBrowserViewComponent_Create).Call(lcl.CheckPtr(AOwner), uintptr(unsafe.Pointer(&result)))
return &TCEFBrowserViewComponent{instance: unsafe.Pointer(result)}
}
// CreateBrowserView
func (m *TCEFBrowserViewComponent) CreateBrowserView(client *ICefClient, url string, requestContextSettings *TCefRequestContextSettings, browserSettings *TCefBrowserSettings, extraInfo *ICefDictionaryValue) {
contextSettingsPtr := requestContextSettings.ToPtr()
browserSettingsPtr := browserSettings.ToPtr()
var dataBytes = []byte{}
var dataBytesPtr unsafe.Pointer
var dataBytesLen int = 0
var argsLen int = 0
if extraInfo != nil && extraInfo.dataLen > 0 {
defer func() {
extraInfo.Clear()
extraInfo = nil
dataBytes = nil
dataBytesPtr = nil
}()
dataBytes = extraInfo.Package()
argsLen = extraInfo.dataLen
dataBytesPtr = unsafe.Pointer(&dataBytes[0])
dataBytesLen = len(dataBytes) - 1
} else {
dataBytesPtr = unsafe.Pointer(&dataBytes)
if extraInfo == nil {
extraInfo = DictionaryValueRef.New()
}
imports.Proc(internale_CEFBrowserViewComponent_CreateBrowserView).Call(uintptr(m.instance), uintptr(client.instance), api.PascalStr(url), uintptr(unsafe.Pointer(&contextSettingsPtr)), uintptr(unsafe.Pointer(&browserSettingsPtr)), uintptr(argsLen), uintptr(dataBytesPtr), uintptr(dataBytesLen))
imports.Proc(internale_CEFBrowserViewComponent_CreateBrowserView).Call(m.Instance(), uintptr(client.instance), api.PascalStr(url), uintptr(unsafe.Pointer(&contextSettingsPtr)), uintptr(unsafe.Pointer(&browserSettingsPtr)), extraInfo.Instance())
}
// Instance
......@@ -66,104 +50,79 @@ func (m *TCEFBrowserViewComponent) Instance() uintptr {
// GetForBrowser
func (m *TCEFBrowserViewComponent) GetForBrowser(browser *ICefBrowser) {
imports.Proc(internale_CEFBrowserViewComponent_CreateBrowserView).Call(uintptr(m.instance), uintptr(browser.Identifier()))
imports.Proc(internale_CEFBrowserViewComponent_GetForBrowser).Call(m.Instance(), browser.Instance())
}
// SetPreferAccelerators
func (m *TCEFBrowserViewComponent) SetPreferAccelerators(preferAccelerators bool) {
imports.Proc(internale_CEFBrowserViewComponent_SetPreferAccelerators).Call(uintptr(m.instance), api.PascalBool(preferAccelerators))
imports.Proc(internale_CEFBrowserViewComponent_SetPreferAccelerators).Call(m.Instance(), api.PascalBool(preferAccelerators))
}
// RequestFocus
func (m *TCEFBrowserViewComponent) RequestFocus() {
imports.Proc(internale_CEFBrowserViewComponent_RequestFocus).Call(uintptr(m.instance))
imports.Proc(internale_CEFBrowserViewComponent_RequestFocus).Call(m.Instance())
}
// Browser
func (m *TCEFBrowserViewComponent) Browser() *ICefBrowser {
r1, _, _ := imports.Proc(internale_CEFBrowserViewComponent_Browser).Call(uintptr(m.instance))
browser := &ICefBrowser{
browseId: int32(r1),
}
return browser
var result uintptr
imports.Proc(internale_CEFBrowserViewComponent_Browser).Call(m.Instance(), uintptr(unsafe.Pointer(&result)))
return &ICefBrowser{instance: unsafe.Pointer(result)}
}
//func (m *TCEFBrowserViewComponent) BrowserView() {
// Proc(internale_CEFBrowserViewComponent_BrowserView).Call(uintptr(m.instance))
// Proc(internale_CEFBrowserViewComponent_BrowserView).Call(m.Instance())
//}
// SetOnBrowserCreated
func (m *TCEFBrowserViewComponent) SetOnBrowserCreated(fn BrowserViewComponentOnBrowserCreated) {
imports.Proc(internale_CEFBrowserViewComponent_SetOnBrowserCreated).Call(uintptr(m.instance), api.MakeEventDataPtr(fn))
imports.Proc(internale_CEFBrowserViewComponent_SetOnBrowserCreated).Call(m.Instance(), api.MakeEventDataPtr(fn))
}
// SetOnBrowserDestroyed
func (m *TCEFBrowserViewComponent) SetOnBrowserDestroyed(fn BrowserViewComponentOnBrowserDestroyed) {
imports.Proc(internale_CEFBrowserViewComponent_SetOnBrowserDestroyed).Call(uintptr(m.instance), api.MakeEventDataPtr(fn))
imports.Proc(internale_CEFBrowserViewComponent_SetOnBrowserDestroyed).Call(m.Instance(), api.MakeEventDataPtr(fn))
}
// SetOnGetDelegateForPopupBrowserView
func (m *TCEFBrowserViewComponent) SetOnGetDelegateForPopupBrowserView(fn BrowserViewComponentOnGetDelegateForPopupBrowserView) {
imports.Proc(internale_CEFBrowserViewComponent_SetOnGetDelegateForPopupBrowserView).Call(uintptr(m.instance), api.MakeEventDataPtr(fn))
imports.Proc(internale_CEFBrowserViewComponent_SetOnGetDelegateForPopupBrowserView).Call(m.Instance(), api.MakeEventDataPtr(fn))
}
// SetOnPopupBrowserViewCreated
func (m *TCEFBrowserViewComponent) SetOnPopupBrowserViewCreated(fn BrowserViewComponentOnPopupBrowserViewCreated) {
imports.Proc(internale_CEFBrowserViewComponent_SetOnPopupBrowserViewCreated).Call(uintptr(m.instance), api.MakeEventDataPtr(fn))
imports.Proc(internale_CEFBrowserViewComponent_SetOnPopupBrowserViewCreated).Call(m.Instance(), api.MakeEventDataPtr(fn))
}
// SetOnGetChromeToolbarType
func (m *TCEFBrowserViewComponent) SetOnGetChromeToolbarType(fn BrowserViewComponentOnGetChromeToolbarType) {
imports.Proc(internale_CEFBrowserViewComponent_SetOnGetChromeToolbarType).Call(uintptr(m.instance), api.MakeEventDataPtr(fn))
imports.Proc(internale_CEFBrowserViewComponent_SetOnGetChromeToolbarType).Call(m.Instance(), api.MakeEventDataPtr(fn))
}
func init() {
lcl.RegisterExtEventCallback(func(fn interface{}, getVal func(idx int) uintptr) bool {
defer func() {
if err := recover(); err != nil {
logger.Error("TCEFBrowserViewComponent Error:", err)
}
}()
getPtr := func(i int) unsafe.Pointer {
return unsafe.Pointer(getVal(i))
}
switch fn.(type) {
case BrowserViewComponentOnBrowserCreated:
browserView := &ICefBrowserView{
instance: getPtr(1),
}
browser := &ICefBrowser{
browseId: int32(getVal(2)),
}
browserView := &ICefBrowserView{instance: getPtr(1)}
browser := &ICefBrowser{instance: getPtr(2)}
fn.(BrowserViewComponentOnBrowserCreated)(lcl.AsObject(getPtr(0)), browserView, browser)
case BrowserViewComponentOnBrowserDestroyed:
browserView := &ICefBrowserView{
instance: getPtr(1),
}
browser := &ICefBrowser{
browseId: int32(getVal(2)),
}
browserView := &ICefBrowserView{instance: getPtr(1)}
browser := &ICefBrowser{instance: getPtr(2)}
fn.(BrowserViewComponentOnBrowserDestroyed)(lcl.AsObject(getPtr(0)), browserView, browser)
case BrowserViewComponentOnGetDelegateForPopupBrowserView:
browserView := &ICefBrowserView{
instance: getPtr(1),
}
browserView := &ICefBrowserView{instance: getPtr(1)}
browserSettingsPtr := (*tCefBrowserSettingsPtr)(getPtr(2))
browserSettings := browserSettingsPtr.Convert()
client := &ICefClient{
instance: getPtr(3),
}
result := &ICefBrowserViewDelegate{
instance: getPtr(5),
}
client := &ICefClient{instance: getPtr(3)}
result := &ICefBrowserViewDelegate{instance: getPtr(5)}
fn.(BrowserViewComponentOnGetDelegateForPopupBrowserView)(lcl.AsObject(getPtr(0)), browserView, browserSettings, client, api.GoBool(getVal(4)), result)
case BrowserViewComponentOnPopupBrowserViewCreated:
browserView := &ICefBrowserView{
instance: getPtr(1),
}
popupBrowserView := &ICefBrowserView{
instance: getPtr(2),
}
browserView := &ICefBrowserView{instance: getPtr(1)}
popupBrowserView := &ICefBrowserView{instance: getPtr(2)}
fn.(BrowserViewComponentOnPopupBrowserViewCreated)(lcl.AsObject(getPtr(0)), browserView, popupBrowserView, api.GoBool(getVal(3)), (*bool)(getPtr(4)))
case BrowserViewComponentOnGetChromeToolbarType:
fn.(BrowserViewComponentOnGetChromeToolbarType)(lcl.AsObject(getPtr(0)), (*consts.TCefChromeToolbarType)(getPtr(1)))
......
......@@ -12,7 +12,7 @@ package cef
import "unsafe"
// ICefBrowserViewDelegate TODO 未实现
// ICefBrowserViewDelegate TODO 未实现
type ICefBrowserViewDelegate struct {
instance unsafe.Pointer
}
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
// CEF Browser View
package cef
import (
"github.com/energye/energy/v2/common/imports"
"github.com/energye/golcl/lcl/api"
"unsafe"
)
func (m *ICefBrowserView) Instance() uintptr {
if m == nil {
return 0
}
return uintptr(m.instance)
}
func (m *ICefBrowserView) Browser() *ICefBrowser {
var result uintptr
imports.Proc(internale_CefBrowserView_Browser).Call(m.Instance(), uintptr(unsafe.Pointer(&result)))
return &ICefBrowser{instance: unsafe.Pointer(result)}
}
func (m *ICefBrowserView) ChromeToolbar() *ICefView {
var result uintptr
imports.Proc(internale_CefBrowserView_ChromeToolbar).Call(m.Instance(), uintptr(unsafe.Pointer(&result)))
return &ICefView{instance: unsafe.Pointer(result)}
}
func (m *ICefBrowserView) SetPreferAccelerators(preferAccelerators bool) {
imports.Proc(internale_CefBrowserView_SetPreferAccelerators).Call(m.Instance(), api.PascalBool(preferAccelerators))
}
......@@ -11,10 +11,11 @@
//go:build !windows
// LCL窗口组件定义和实现-非windows平台
package cef
import (
"github.com/energye/energy/common"
"github.com/energye/energy/v2/common"
"github.com/energye/golcl/lcl/types"
)
......
......@@ -11,10 +11,11 @@
//go:build windows
// LCL窗口组件定义和实现-windows平台
package cef
import (
"github.com/energye/energy/consts"
"github.com/energye/energy/v2/consts"
"github.com/energye/golcl/lcl"
"github.com/energye/golcl/lcl/rtl"
"github.com/energye/golcl/lcl/types"
......@@ -99,19 +100,19 @@ func (m *customWindowCaption) onNCMouseMove(message *types.TMessage, lResult *ty
func (m *customWindowCaption) onSetCursor(message *types.TMessage, lResult *types.LRESULT, aHandled *bool) {
if m.canBorder { //当前在边框
switch LOWORD(uint32(message.LParam)) {
case HTBOTTOMRIGHT, HTTOPLEFT: //右下 左上
case consts.HTBOTTOMRIGHT, consts.HTTOPLEFT: //右下 左上
*lResult = types.LRESULT(m.borderHT)
*aHandled = true
WinSetCursor(WinLoadCursor(0, IDC_SIZENWSE))
case HTRIGHT, HTLEFT: //右 左
case consts.HTRIGHT, consts.HTLEFT: //右 左
*lResult = types.LRESULT(m.borderHT)
*aHandled = true
WinSetCursor(WinLoadCursor(0, IDC_SIZEWE))
case HTTOPRIGHT, HTBOTTOMLEFT: //右上 左下
case consts.HTTOPRIGHT, consts.HTBOTTOMLEFT: //右上 左下
*lResult = types.LRESULT(m.borderHT)
*aHandled = true
WinSetCursor(WinLoadCursor(0, IDC_SIZENESW))
case HTTOP, HTBOTTOM: //上 下
case consts.HTTOP, consts.HTBOTTOM: //上 下
*lResult = types.LRESULT(m.borderHT)
*aHandled = true
WinSetCursor(WinLoadCursor(0, IDC_SIZENS))
......@@ -123,35 +124,35 @@ func (m *customWindowCaption) onSetCursor(message *types.TMessage, lResult *type
func (m *customWindowCaption) onCanBorder(x, y int32, rect *types.TRect) (int, bool) {
if m.canBorder = x <= rect.Width() && x >= rect.Width()-angleRange && y <= angleRange; m.canBorder { // 右上
m.borderWMSZ = WMSZ_TOPRIGHT
m.borderHT = HTTOPRIGHT
m.borderHT = consts.HTTOPRIGHT
return m.borderHT, true
} else if m.canBorder = x <= rect.Width() && x >= rect.Width()-angleRange && y <= rect.Height() && y >= rect.Height()-angleRange; m.canBorder { // 右下
m.borderWMSZ = WMSZ_BOTTOMRIGHT
m.borderHT = HTBOTTOMRIGHT
m.borderHT = consts.HTBOTTOMRIGHT
return m.borderHT, true
} else if m.canBorder = x <= angleRange && y <= angleRange; m.canBorder { //左上
m.borderWMSZ = WMSZ_TOPLEFT
m.borderHT = HTTOPLEFT
m.borderHT = consts.HTTOPLEFT
return m.borderHT, true
} else if m.canBorder = x <= angleRange && y >= rect.Height()-angleRange; m.canBorder { //左下
m.borderWMSZ = WMSZ_BOTTOMLEFT
m.borderHT = HTBOTTOMLEFT
m.borderHT = consts.HTBOTTOMLEFT
return m.borderHT, true
} else if m.canBorder = x > angleRange && x < rect.Width()-angleRange && y <= borderRange; m.canBorder { //上
m.borderWMSZ = WMSZ_TOP
m.borderHT = HTTOP
m.borderHT = consts.HTTOP
return m.borderHT, true
} else if m.canBorder = x > angleRange && x < rect.Width()-angleRange && y >= rect.Height()-borderRange; m.canBorder { //下
m.borderWMSZ = WMSZ_BOTTOM
m.borderHT = HTBOTTOM
m.borderHT = consts.HTBOTTOM
return m.borderHT, true
} else if m.canBorder = x <= borderRange && y > angleRange && y < rect.Height()-angleRange; m.canBorder { //左
m.borderWMSZ = WMSZ_LEFT
m.borderHT = HTLEFT
m.borderHT = consts.HTLEFT
return m.borderHT, true
} else if m.canBorder = x <= rect.Width() && x >= rect.Width()-borderRange && y > angleRange && y < rect.Height()-angleRange; m.canBorder { // 右
m.borderWMSZ = WMSZ_RIGHT
m.borderHT = HTRIGHT
m.borderHT = consts.HTRIGHT
return m.borderHT, true
}
return 0, false
......@@ -161,18 +162,18 @@ func (m *customWindowCaption) onCanBorder(x, y int32, rect *types.TRect) (int, b
func (m *customWindowCaption) onNCLButtonDown(hWND types.HWND, message *types.TMessage, lResult *types.LRESULT, aHandled *bool) {
if m.canCaption { // 标题栏
x, y := m.toPoint(message)
*lResult = HTCAPTION
*lResult = consts.HTCAPTION
m.borderMD = true
*aHandled = true
win.ReleaseCapture()
rtl.PostMessage(hWND, WM_NCLBUTTONDOWN, HTCAPTION, rtl.MakeLParam(uint16(x), uint16(y)))
rtl.PostMessage(hWND, consts.WM_NCLBUTTONDOWN, consts.HTCAPTION, rtl.MakeLParam(uint16(x), uint16(y)))
} else if m.canBorder { // 边框
x, y := m.toPoint(message)
*lResult = types.LRESULT(m.borderHT)
m.borderMD = true
*aHandled = true
win.ReleaseCapture()
rtl.PostMessage(hWND, WM_SYSCOMMAND, uintptr(SC_SIZE|m.borderWMSZ), rtl.MakeLParam(uint16(x), uint16(y)))
rtl.PostMessage(hWND, consts.WM_SYSCOMMAND, uintptr(consts.SC_SIZE|m.borderWMSZ), rtl.MakeLParam(uint16(x), uint16(y)))
//rtl.PostMessage(hWND, WM_SYSCOMMAND, uintptr(SC_SIZE|m.borderWMSZ), 0)
}
}
......@@ -206,32 +207,32 @@ func (m *customWindowCaption) isCaption(hWND types.HWND, message *types.TMessage
// doOnRenderCompMsg
func (m *LCLBrowserWindow) doOnRenderCompMsg(message *types.TMessage, lResult *types.LRESULT, aHandled *bool) {
switch message.Msg {
case WM_NCLBUTTONDBLCLK: // 163 NC left dclick
case consts.WM_NCLBUTTONDBLCLK: // 163 NC left dclick
//标题栏拖拽区域 双击最大化和还原
if m.cwcap.canCaption && m.WindowProperty().EnableWebkitAppRegionDClk {
*lResult = HTCAPTION
*lResult = consts.HTCAPTION
*aHandled = true
win.ReleaseCapture()
m.windowProperty.windowState = m.WindowState()
if m.windowProperty.windowState == types.WsNormal {
rtl.PostMessage(m.Handle(), WM_SYSCOMMAND, SC_MAXIMIZE, 0)
rtl.PostMessage(m.Handle(), consts.WM_SYSCOMMAND, consts.SC_MAXIMIZE, 0)
} else {
rtl.PostMessage(m.Handle(), WM_SYSCOMMAND, SC_RESTORE, 0)
rtl.PostMessage(m.Handle(), consts.WM_SYSCOMMAND, consts.SC_RESTORE, 0)
}
rtl.SendMessage(m.Handle(), WM_NCLBUTTONUP, HTCAPTION, 0)
rtl.SendMessage(m.Handle(), consts.WM_NCLBUTTONUP, consts.HTCAPTION, 0)
}
case WM_NCLBUTTONDOWN: // 161 nc left down
case consts.WM_NCLBUTTONDOWN: // 161 nc left down
m.cwcap.onNCLButtonDown(m.Handle(), message, lResult, aHandled)
case WM_NCLBUTTONUP: // 162 nc l up
case consts.WM_NCLBUTTONUP: // 162 nc l up
if m.cwcap.canCaption {
*lResult = HTCAPTION
*lResult = consts.HTCAPTION
*aHandled = true
}
case WM_NCMOUSEMOVE: // 160 nc mouse move
case consts.WM_NCMOUSEMOVE: // 160 nc mouse move
m.cwcap.onNCMouseMove(message, lResult, aHandled)
case WM_SETCURSOR: // 32 设置鼠标图标样式
case consts.WM_SETCURSOR: // 32 设置鼠标图标样式
m.cwcap.onSetCursor(message, lResult, aHandled)
case WM_NCHITTEST: // 132 NCHITTEST
case consts.WM_NCHITTEST: // 132 NCHITTEST
if m.cwcap.borderMD { //TODO 测试windows7, 161消息之后再次处理132消息导致消息错误
m.cwcap.borderMD = false
return
......@@ -239,7 +240,7 @@ func (m *LCLBrowserWindow) doOnRenderCompMsg(message *types.TMessage, lResult *t
//鼠标坐标是否在标题区域
x, y, caption := m.cwcap.isCaption(m.Handle(), message)
if caption { //窗口标题栏
*lResult = HTCAPTION
*lResult = consts.HTCAPTION
*aHandled = true
} else if m.WindowProperty().EnableHideCaption && m.WindowProperty().EnableResize && m.WindowState() == types.WsNormal { //1.窗口隐藏标题栏 2.启用了调整窗口大小 3.非最大化、最小化、全屏状态
rect := m.BoundsRect()
......@@ -280,7 +281,7 @@ func (m *LCLBrowserWindow) setDraggableRegions() {
// 注册windows下CompMsg事件
func (m *LCLBrowserWindow) registerWindowsCompMsgEvent() {
var bwEvent = BrowserWindow.browserEvent
m.chromium.SetOnRenderCompMsg(func(sender lcl.IObject, message *types.TMessage, lResult *types.LRESULT, aHandled *bool) {
m.Chromium().SetOnRenderCompMsg(func(sender lcl.IObject, message *types.TMessage, lResult *types.LRESULT, aHandled *bool) {
if bwEvent.onRenderCompMsg != nil {
bwEvent.onRenderCompMsg(sender, message, lResult, aHandled)
}
......@@ -317,9 +318,9 @@ func (m *LCLBrowserWindow) Maximize() {
win.ReleaseCapture()
m.windowProperty.windowState = m.WindowState()
if m.windowProperty.windowState == types.WsNormal {
rtl.PostMessage(m.Handle(), WM_SYSCOMMAND, SC_MAXIMIZE, 0)
rtl.PostMessage(m.Handle(), consts.WM_SYSCOMMAND, consts.SC_MAXIMIZE, 0)
} else {
rtl.SendMessage(m.Handle(), WM_SYSCOMMAND, SC_RESTORE, 0)
rtl.SendMessage(m.Handle(), consts.WM_SYSCOMMAND, consts.SC_RESTORE, 0)
}
})
}
......
......@@ -9,13 +9,16 @@
//----------------------------------------
// VF窗口组件定义和实现
package cef
import (
"github.com/energye/energy/common"
"github.com/energye/energy/common/assetserve"
"github.com/energye/energy/consts"
"github.com/energye/energy/ipc"
"github.com/energye/energy/v2/cef/internal/ipc"
"github.com/energye/energy/v2/cef/internal/window"
"github.com/energye/energy/v2/cef/process"
"github.com/energye/energy/v2/consts"
"github.com/energye/energy/v2/logger"
"github.com/energye/energy/v2/pkgs/assetserve"
"github.com/energye/golcl/energy/emfs"
"github.com/energye/golcl/energy/tools"
"github.com/energye/golcl/lcl"
......@@ -33,12 +36,10 @@ type ViewsFrameworkBrowserWindow struct {
windowType consts.WINDOW_TYPE //0:browser 1:devTools 2:viewSource 默认:0
windowId int32 //
chromium IChromium //
browser *ICefBrowser //
component lcl.IComponent //
windowComponent *TCEFWindowComponent //
browserViewComponent *TCEFBrowserViewComponent //
windowProperty *WindowProperty //窗口属性
frames TCEFFrame //当前浏览器下的所有frame
auxTools *auxTools //辅助工具
tray ITray //托盘
doOnWindowCreated WindowComponentOnWindowCreated //窗口创建
......@@ -82,11 +83,15 @@ func NewViewsFrameworkBrowserWindow(chromiumConfig *tCefChromiumConfig, windowPr
}
if windowProperty.IconFS != "" {
if emfs.IsExist(windowProperty.IconFS) {
_ = m.windowComponent.SetWindowAppIconFS(1, windowProperty.IconFS)
if err := m.windowComponent.SetWindowAppIconByFSFile(1, windowProperty.IconFS); err != nil {
logger.Error("set window application icon error:", err.Error())
}
}
} else if windowProperty.Icon != "" {
if tools.IsExist(windowProperty.Icon) {
_ = m.windowComponent.SetWindowAppIcon(1, windowProperty.Icon)
if err := m.windowComponent.SetWindowAppIconByFile(1, windowProperty.Icon); err != nil {
logger.Error("set window application icon error:", err.Error())
}
}
}
m.browserViewComponent.RequestFocus()
......@@ -100,44 +105,43 @@ func NewViewsFrameworkBrowserWindow(chromiumConfig *tCefChromiumConfig, windowPr
}
// ViewsFrameworkBrowserWindow 主窗口初始化
func (m *browser) appContextInitialized(app *TCEFApplication) {
if !common.Args.IsMain() {
func (m *browserWindow) appContextInitialized(app *TCEFApplication) {
if !process.Args.IsMain() {
return
}
app.SetOnContextInitialized(func() {
m.Config.WindowProperty.WindowType = consts.WT_MAIN_BROWSER
vFrameBrowserWindow := NewViewsFrameworkBrowserWindow(m.Config.ChromiumConfig(), m.Config.WindowProperty)
vFrameBrowserWindow.Chromium().SetOnBeforeClose(func(sender lcl.IObject, browser *ICefBrowser) {
chromiumOnBeforeClose(browser)
if vFrameBrowserWindow.tray != nil {
vFrameBrowserWindow.tray.close()
}
})
// 重置窗口属性, 注册默认实现事件
vFrameBrowserWindow.ResetWindowPropertyForEvent()
vFrameBrowserWindow.windowId = BrowserWindow.GetNextWindowNum()
vFrameBrowserWindow.putChromiumWindowInfo()
vFrameBrowserWindow.registerPopupEvent()
vFrameBrowserWindow.registerDefaultEvent()
vFrameBrowserWindow.windowComponent.SetOnCanClose(func(sender lcl.IObject, window *ICefWindow, aResult *bool) {
*aResult = true
app.QuitMessageLoop()
})
vFrameBrowserWindow.doOnWindowCreated = func(sender lcl.IObject, window *ICefWindow) {
if m.Config.browserWindowAfterOnEventCallback != nil {
m.Config.browserWindowAfterOnEventCallback(vFrameBrowserWindow)
}
}
BrowserWindow.mainVFBrowserWindow = vFrameBrowserWindow
if m.Config.browserWindowOnEventCallback != nil {
BrowserWindow.browserEvent.chromium = vFrameBrowserWindow.chromium
m.Config.browserWindowOnEventCallback(BrowserWindow.browserEvent, vFrameBrowserWindow)
}
vFrameBrowserWindow.windowComponent.CreateTopLevelWindow()
ipc.SetProcessMessage(vFrameBrowserWindow.Chromium().(*TCEFChromium))
vFrameBrowserWindow.CreateTopLevelWindow()
})
}
// registerPopupEvent 注册弹出子窗口事件
func (m *ViewsFrameworkBrowserWindow) registerPopupEvent() {
var bwEvent = BrowserWindow.browserEvent
m.chromium.SetOnBeforeClose(func(sender lcl.IObject, browser *ICefBrowser) {
chromiumOnBeforeClose(browser)
})
m.chromium.SetOnBeforePopup(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, beforePopupInfo *BeforePopupInfo, client *ICefClient, noJavascriptAccess *bool) bool {
if !api.GoBool(BrowserWindow.Config.chromiumConfig.enableWindowPopup) {
return true
......@@ -152,12 +156,9 @@ func (m *ViewsFrameworkBrowserWindow) registerPopupEvent() {
}
if !result {
vfbw.ResetWindowPropertyForEvent()
vfbw.SetWindowType(consts.WT_POPUP_SUB_BROWSER)
vfbw.windowId = BrowserWindow.GetNextWindowNum()
vfbw.putChromiumWindowInfo()
vfbw.registerPopupEvent()
vfbw.registerDefaultEvent()
vfbw.windowComponent.CreateTopLevelWindow()
vfbw.CreateTopLevelWindow()
result = true
}
return result
......@@ -206,7 +207,7 @@ func (m *ViewsFrameworkBrowserWindow) registerDefaultEvent() {
var bwEvent = BrowserWindow.browserEvent
//默认自定义快捷键
defaultAcceleratorCustom()
m.chromium.SetOnProcessMessageReceived(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, sourceProcess consts.CefProcessId, message *ipc.ICefProcessMessage) bool {
m.chromium.SetOnProcessMessageReceived(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, sourceProcess consts.CefProcessId, message *ICefProcessMessage) bool {
if bwEvent.onProcessMessageReceived != nil {
return bwEvent.onProcessMessageReceived(sender, browser, frame, sourceProcess, message)
}
......@@ -220,15 +221,13 @@ func (m *ViewsFrameworkBrowserWindow) registerDefaultEvent() {
bwEvent.onBeforeResourceLoad(sender, browser, frame, request, callback, result)
}
})
//事件可以覆盖
m.chromium.SetOnBeforeDownload(func(sender lcl.IObject, browser *ICefBrowser, beforeDownloadItem *DownloadItem, suggestedName string, callback *ICefBeforeDownloadCallback) {
m.chromium.SetOnBeforeDownload(func(sender lcl.IObject, browser *ICefBrowser, beforeDownloadItem *ICefDownloadItem, suggestedName string, callback *ICefBeforeDownloadCallback) {
if bwEvent.onBeforeDownload != nil {
bwEvent.onBeforeDownload(sender, browser, beforeDownloadItem, suggestedName, callback)
} else {
callback.Cont(consts.ExePath+consts.Separator+suggestedName, true)
}
})
//事件可以覆盖
m.chromium.SetOnBeforeContextMenu(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, model *ICefMenuModel) {
if bwEvent.onBeforeContextMenu != nil {
bwEvent.onBeforeContextMenu(sender, browser, frame, params, model)
......@@ -236,7 +235,6 @@ func (m *ViewsFrameworkBrowserWindow) registerDefaultEvent() {
chromiumOnBeforeContextMenu(sender, browser, frame, params, model)
}
})
//事件可以覆盖
m.chromium.SetOnContextMenuCommand(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, commandId consts.MenuId, eventFlags uint32, result *bool) {
if bwEvent.onContextMenuCommand != nil {
bwEvent.onContextMenuCommand(sender, browser, frame, params, commandId, eventFlags, result)
......@@ -245,7 +243,6 @@ func (m *ViewsFrameworkBrowserWindow) registerDefaultEvent() {
}
})
m.chromium.SetOnFrameCreated(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame) {
BrowserWindow.putBrowserFrame(browser, frame)
if bwEvent.onFrameCreated != nil {
bwEvent.onFrameCreated(sender, browser, frame)
}
......@@ -264,10 +261,9 @@ func (m *ViewsFrameworkBrowserWindow) registerDefaultEvent() {
bwEvent.onAfterCreated(sender, browser)
}
})
//事件可以被覆盖
m.chromium.SetOnKeyEvent(func(sender lcl.IObject, browser *ICefBrowser, event *TCefKeyEvent, result *bool) {
m.chromium.SetOnKeyEvent(func(sender lcl.IObject, browser *ICefBrowser, event *TCefKeyEvent, osEvent *consts.TCefEventHandle, result *bool) {
if bwEvent.onKeyEvent != nil {
bwEvent.onKeyEvent(sender, browser, event, result)
bwEvent.onKeyEvent(sender, browser, event, osEvent, result)
} else {
if api.GoBool(BrowserWindow.Config.chromiumConfig.enableDevTools) {
if winInfo := BrowserWindow.GetWindowInfo(browser.Identifier()); winInfo != nil {
......@@ -275,10 +271,10 @@ func (m *ViewsFrameworkBrowserWindow) registerDefaultEvent() {
return
}
}
if event.WindowsKeyCode == VkF12 && event.Kind == consts.KEYEVENT_RAW_KEYDOWN {
if event.WindowsKeyCode == consts.VkF12 && event.Kind == consts.KEYEVENT_RAW_KEYDOWN {
browser.ShowDevTools()
*result = true
} else if event.WindowsKeyCode == VkF12 && event.Kind == consts.KEYEVENT_KEYUP {
} else if event.WindowsKeyCode == consts.VkF12 && event.Kind == consts.KEYEVENT_KEYUP {
*result = true
}
}
......@@ -287,10 +283,9 @@ func (m *ViewsFrameworkBrowserWindow) registerDefaultEvent() {
}
}
})
m.chromium.SetOnBeforeBrowser(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame) bool {
chromiumOnBeforeBrowser(browser, frame)
m.chromium.SetOnBeforeBrowser(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest, userGesture, isRedirect bool) bool {
if bwEvent.onBeforeBrowser != nil {
return bwEvent.onBeforeBrowser(sender, browser, frame)
return bwEvent.onBeforeBrowser(sender, browser, frame, request, userGesture, isRedirect)
}
return false
})
......@@ -352,11 +347,6 @@ func (m *ViewsFrameworkBrowserWindow) WindowProperty() *WindowProperty {
return m.windowProperty
}
// putChromiumWindowInfo
func (m *ViewsFrameworkBrowserWindow) putChromiumWindowInfo() {
BrowserWindow.putWindowInfo(m.windowId, m)
}
// BrowserWindow 返回VF窗口组件实现
func (m *ViewsFrameworkBrowserWindow) BrowserWindow() *ViewsFrameworkBrowserWindow {
return m
......@@ -452,30 +442,7 @@ func (m *ViewsFrameworkBrowserWindow) createAuxTools() {
// Browser 返回browser
func (m *ViewsFrameworkBrowserWindow) Browser() *ICefBrowser {
return m.browser
}
// Frames 获取Frames
func (m *ViewsFrameworkBrowserWindow) Frames() TCEFFrame {
return m.frames
}
// createFrames 创建TCEFFrame
func (m *ViewsFrameworkBrowserWindow) createFrames() {
if m.frames == nil {
m.frames = make(TCEFFrame)
}
}
// setBrowser
func (m *ViewsFrameworkBrowserWindow) setBrowser(browser *ICefBrowser) {
m.browser = browser
}
// addFrame
func (m *ViewsFrameworkBrowserWindow) addFrame(frame *ICefFrame) {
m.createFrames()
m.frames[frame.Id] = frame
return m.Chromium().Browser()
}
// Chromium 返回 chromium
......@@ -485,6 +452,9 @@ func (m *ViewsFrameworkBrowserWindow) Chromium() IChromium {
// Id 获取窗口ID
func (m *ViewsFrameworkBrowserWindow) Id() int32 {
if m.windowId == 0 {
m.windowId = m.Chromium().BrowserId()
}
return m.windowId
}
......@@ -543,6 +513,9 @@ func (m *ViewsFrameworkBrowserWindow) CloseBrowserWindow() {
// CreateTopLevelWindow 创建顶层窗口
func (m *ViewsFrameworkBrowserWindow) CreateTopLevelWindow() {
if m.WindowType() != consts.WT_DEV_TOOLS {
window.CurrentBrowseWindowCache = m
}
m.WindowComponent().CreateTopLevelWindow()
}
......
......@@ -11,6 +11,7 @@
//go:build !windows
// VF窗口组件定义和实现-非windows平台
package cef
import "github.com/energye/golcl/lcl"
......
......@@ -11,6 +11,7 @@
//go:build windows
// VF窗口组件定义和实现-windows平台
package cef
import (
......
......@@ -8,11 +8,13 @@
//
//----------------------------------------
// 窗口定义
// LCL + Energy 窗口属性
// 提供了常用属性配置, 如果使用更复杂的配置需要直接使用LCL提供的窗口属性配置
package cef
import (
"github.com/energye/energy/consts"
"github.com/energye/energy/v2/consts"
"github.com/energye/golcl/lcl"
"github.com/energye/golcl/lcl/types"
)
......@@ -88,9 +90,6 @@ type IBrowserWindow interface {
IsClosing() bool //返回窗口是否正在关闭/或已关闭 true正在或已关闭
AsViewsFrameworkBrowserWindow() IViewsFrameworkBrowserWindow //转换为ViewsFramework窗口接口, 失败返回nil
AsLCLBrowserWindow() ILCLBrowserWindow //转换为LCL窗口接口, 失败返回nil
Frames() TCEFFrame //窗口内的所有Frame
addFrame(frame *ICefFrame) //
setBrowser(browser *ICefBrowser) //
EnableAllDefaultEvent() //启用所有默认事件
SetTitle(title string) //设置窗口标题栏标题
IsViewsFramework() bool //是否为 IViewsFrameworkBrowserWindow 窗口,失败返回false
......@@ -122,7 +121,7 @@ type ILCLBrowserWindow interface {
IBrowserWindow
BrowserWindow() *LCLBrowserWindow //返回 LCLBrowserWindow 窗口结构
EnableDefaultCloseEvent() //启用默认关闭事件
WindowParent() ITCefWindowParent //浏览器父窗口组件
WindowParent() ICEFWindowParent //浏览器父窗口组件
DisableTransparent() //禁用窗口透明
EnableTransparent(value uint8) //用用并设置窗口透明
DisableSystemMenu() //禁用标题栏系统菜单
......
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
// 应用程序的配置
// 提供部分应用程序配置
package cef
import (
"github.com/energye/energy/cef/i18n"
"github.com/energye/energy/common"
"github.com/energye/energy/common/imports"
. "github.com/energye/energy/consts"
"github.com/energye/golcl/energy/tools"
"github.com/energye/golcl/lcl/api"
"os"
"path/filepath"
)
// Application 支持的配置
type tCefApplicationConfig struct {
frameworkDirPath uintptr //string cef框架根目录
resourcesDirPath uintptr //string
localesDirPath uintptr //string
cache uintptr //string
userDataPath uintptr //string
language uintptr //string 语言设置
localesRequired uintptr //string 默认空,检查所有的语言环境 逗号分隔
logFile uintptr //string
mainBundlePath uintptr //string 只对 darwin 启作用
browseSubprocessPath uintptr //string 只对 非darwin 启作用
logSeverity uintptr //uint32
noSandbox uintptr //bool
disableZygote uintptr //bool 只对 linux 启作用
enableGPU uintptr //bool
singleProcess uintptr //bool 进程启动模式,多进程:false 单进程:true 默认false
useMockKeyChain uintptr //bool
checkCEFFiles uintptr //bool
remoteDebuggingPort uintptr //int32
externalMessagePump uintptr //bool
multiThreadedMessageLoop uintptr //bool
chromeRuntime uintptr //bool
}
// 创建应用全局配置
func NewApplicationConfig() *tCefApplicationConfig {
m := &tCefApplicationConfig{}
m.SetFrameworkDirPath(Empty)
m.SetResourcesDirPath(Empty)
m.SetLocalesDirPath(Empty)
m.SetCache(Empty)
m.SetUserDataPath(Empty)
m.SetLanguage(LANGUAGE_zh_CN)
m.SetLocalesRequired(Empty)
m.SetLogFile(Empty)
m.SetMainBundlePath(Empty)
m.SetBrowseSubprocessPath(Empty)
m.SetLogSeverity(LOGSEVERITY_DISABLE)
m.SetEnableGPU(enableGPU)
m.SetSingleProcess(false)
m.SetUseMockKeyChain(false)
m.SetNoSandbox(true)
m.SetDisableZygote(true)
m.SetCheckCEFFiles(false)
m.SetRemoteDebuggingPort(0)
m.SetChromeRuntime(false)
// 以下条件判断根据不同平台, 启动不同的窗口组件
// ViewsFrameworkBrowserWindow 窗口组件,同时支持 Windows/Linux/MacOSX
// LCL 窗口组件,同时支持 Windows/MacOSX, CEF版本<=106.xx时支持GTK2, CEF版本>=107.xx时默认开启GTK3且不支持GTK2和LCL提供的各种组件
if common.IsLinux() { // (VF)View Framework 窗口
// Linux CEF >= 107.xxx 版本以后,默认启用的GTK3,106及以前版本默认支持GTK2但无法正常输入中文
// 强制使用GTK3方式,但又无法正常创建lcl组件到窗口中,该框架只对浏览器应用做封装
// 所以初衷以浏览器应用建设为目标
// Linux平台默认设置为false,将启用 ViewsFrameworkBrowserWindow 窗口
m.SetExternalMessagePump(false)
m.SetMultiThreadedMessageLoop(false)
} else if common.IsDarwin() { // LCL窗口
// MacOSX 在使用LCL窗口组件必须将ExternalMessagePump=true和MultiThreadedMessageLoop=false
// 或同Linux一样使用ViewsFrameworkBrowserWindow窗口组件
m.SetExternalMessagePump(true)
m.SetMultiThreadedMessageLoop(false)
} else { // LCL窗口
//Windows
m.SetExternalMessagePump(false)
m.SetMultiThreadedMessageLoop(true)
}
return m
}
// 设置 Chromium Framework 编译好的二进制包根目录
//
// 默认当前目录
func (m *tCefApplicationConfig) SetFrameworkDirPath(s string) *tCefApplicationConfig {
m.frameworkDirPath = api.PascalStr(s)
return m
}
// 设置资源目录,默认当前目录
func (m *tCefApplicationConfig) SetResourcesDirPath(s string) *tCefApplicationConfig {
m.resourcesDirPath = api.PascalStr(s)
return m
}
// 设置本地语言目录,默认当前目录
func (m *tCefApplicationConfig) SetLocalesDirPath(s string) *tCefApplicationConfig {
m.localesDirPath = api.PascalStr(s)
return m
}
// 设置缓存目录,默认当前目录
func (m *tCefApplicationConfig) SetCache(s string) *tCefApplicationConfig {
m.cache = api.PascalStr(s)
return m
}
// 设置用户数据目录,默认当前目录
func (m *tCefApplicationConfig) SetUserDataPath(s string) *tCefApplicationConfig {
m.userDataPath = api.PascalStr(s)
return m
}
// 设置进程模型,作用于linux-默认禁用
func (m *tCefApplicationConfig) SetDisableZygote(s bool) *tCefApplicationConfig {
m.disableZygote = api.PascalBool(s)
return m
}
// 设置关闭沙盒-默认关闭
func (m *tCefApplicationConfig) SetNoSandbox(s bool) *tCefApplicationConfig {
m.noSandbox = api.PascalBool(s)
return m
}
// 设置开启关闭GPU加速
func (m *tCefApplicationConfig) SetEnableGPU(s bool) *tCefApplicationConfig {
enableGPU = s
m.enableGPU = api.PascalBool(s)
return m
}
// 设置进程模式,true:单进程模式
func (m *tCefApplicationConfig) SetSingleProcess(s bool) *tCefApplicationConfig {
SingleProcess = s
m.singleProcess = api.PascalBool(s)
return m
}
// 设置使用模拟key chain
func (m *tCefApplicationConfig) SetUseMockKeyChain(s bool) *tCefApplicationConfig {
m.useMockKeyChain = api.PascalBool(s)
return m
}
// 检测CEF文件默认不检测
func (m *tCefApplicationConfig) SetCheckCEFFiles(s bool) *tCefApplicationConfig {
m.checkCEFFiles = api.PascalBool(s)
return m
}
// 设置语言
func (m *tCefApplicationConfig) SetLanguage(s LANGUAGE) *tCefApplicationConfig {
i18n.Switch(s)
m.language = api.PascalStr(string(s))
return m
}
// 设置必备的本地语言支持,逗号分隔的字符串 s="zh-CN,en-US" ,默认情况下 en-US 是必须的
func (m *tCefApplicationConfig) SetLocalesRequired(s string) *tCefApplicationConfig {
m.localesRequired = api.PascalStr(s)
return m
}
// 设置日志文件目录
func (m *tCefApplicationConfig) SetLogFile(s string) *tCefApplicationConfig {
m.logFile = api.PascalStr(s)
return m
}
// 设置主程序绑定目录 作用于macos
func (m *tCefApplicationConfig) SetMainBundlePath(s string) *tCefApplicationConfig {
m.mainBundlePath = api.PascalStr(s)
return m
}
// 设置子进程执行文件目录,一搬用于主进程过于复杂启动慢,需要独立出子进程
func (m *tCefApplicationConfig) SetBrowseSubprocessPath(s string) *tCefApplicationConfig {
m.browseSubprocessPath = api.PascalStr(s)
return m
}
// 设置日志级别
func (m *tCefApplicationConfig) SetLogSeverity(s LOG) *tCefApplicationConfig {
m.logSeverity = uintptr(s)
return m
}
// 设置远程调式端口 (1024 ~ 65535)
func (m *tCefApplicationConfig) SetRemoteDebuggingPort(s int32) *tCefApplicationConfig {
if s > 1024 && s < 65535 {
m.remoteDebuggingPort = uintptr(s)
}
return m
}
func (m *tCefApplicationConfig) SetExternalMessagePump(s bool) *tCefApplicationConfig {
m.externalMessagePump = api.PascalBool(s)
return m
}
func (m *tCefApplicationConfig) SetMultiThreadedMessageLoop(s bool) *tCefApplicationConfig {
m.multiThreadedMessageLoop = api.PascalBool(s)
return m
}
func (m *tCefApplicationConfig) SetChromeRuntime(s bool) *tCefApplicationConfig {
m.chromeRuntime = api.PascalBool(s)
return m
}
// GO绑定JS通用类型所属对象名定义
//
// 默认值 gocobj
func (m *tCefApplicationConfig) SetCommonRootName(name string) {
if name == "" {
name = commonRootName
} else {
commonRootName = name
}
imports.Proc(internale_CEFV8ValueRef_SetCommonRootName).Call(api.PascalStr(commonRootName))
}
// GO绑定JS对象类型所属对象名定义
//
// 默认值 goobj
func (m *tCefApplicationConfig) SetObjectRootName(name string) {
if name == "" {
name = objectRootName
} else {
objectRootName = name
}
imports.Proc(internale_CEFV8ValueRef_SetObjectRootName).Call(api.PascalStr(objectRootName))
}
// energy framework env
func (m *tCefApplicationConfig) framework() {
var path string
if m.frameworkDirPath == 0 {
path = libPath()
} else {
path = api.GoStr(m.frameworkDirPath)
}
if path != "" {
m.SetFrameworkDirPath(path)
if m.cache == 0 {
m.SetCache(filepath.Join(path, "cache"))
}
if m.userDataPath == 0 {
m.SetUserDataPath(filepath.Join(path, "userDataPath"))
}
}
}
func ceflib() string {
if common.IsWindows() {
return "libcef.dll"
} else if common.IsLinux() {
return "libcef.so"
}
return ""
}
func libPath() string {
var lib = ceflib()
if lib != "" {
//当前目录
if tools.IsExist(ExePath + Separator + lib) {
return ExePath
}
//环境变量
var env = os.Getenv(ENERGY_HOME_KEY)
if tools.IsExist(env + Separator + lib) {
return env
}
}
return ""
}
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
//go:build !windows && cgo
// +build !windows,cgo
package cef
//// #cgo darwin CFLAGS: -mmacosx-version-min=10.8 -DMACOSX_DEPLOYMENT_TARGET=10.8
// #cgo darwin CFLAGS: -mmacosx-version-min=10.8
// #cgo darwin LDFLAGS: -mmacosx-version-min=10.8
//
// extern void* doCefIPCCallbackFuncEventProc(void* f, void* args, long argcount);
// static void* doGetCefIPCCallbackFuncEventAddr() {
// return &doCefIPCCallbackFuncEventProc;
// }
//
// extern void* doCefWindowBindEventProc(void* f, void* args, long argcount);
// static void* doGetCefWindowBindEventAddr() {
// return &doCefWindowBindEventProc;
// }
import "C"
import (
"unsafe"
)
//export doCefIPCCallbackFuncEventProc
func doCefIPCCallbackFuncEventProc(f unsafe.Pointer, args unsafe.Pointer, argcount C.long) unsafe.Pointer {
cefIPCEventProc(uintptr(f), uintptr(args), int(argcount))
return nullptr
}
//export doCefWindowBindEventProc
func doCefWindowBindEventProc(f unsafe.Pointer, args unsafe.Pointer, argcount C.long) unsafe.Pointer {
cefWindowBindCallbackEventProc(uintptr(f), uintptr(args), int(argcount))
return nullptr
}
var (
cefIPCCallbackFuncEvent = uintptr(C.doGetCefIPCCallbackFuncEventAddr())
cefWindowBindEvent = uintptr(C.doGetCefWindowBindEventAddr())
)
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
package cef
import "syscall"
var (
cefIPCCallbackFuncEvent = syscall.NewCallback(cefIPCEventProc)
cefWindowBindEvent = syscall.NewCallback(cefWindowBindCallbackEventProc)
)
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
// CEF Chromium组件
package cef
import (
. "github.com/energye/energy/common"
. "github.com/energye/energy/consts"
"github.com/energye/energy/ipc"
"github.com/energye/golcl/lcl"
"github.com/energye/golcl/lcl/types"
"sync"
"unsafe"
)
var executeJS = &ExecuteJS{
msgID: &MsgID{},
emitSync: &ipc.EmitSyncCollection{Mutex: new(sync.Mutex), EmitCollection: sync.Map{}},
emitCallback: &ipc.EmitCallbackCollection{EmitCollection: sync.Map{}},
}
type ExecuteJS struct {
msgID *MsgID //ipc 消息ID生成
emitCallback *ipc.EmitCallbackCollection //回调函数集合
emitSync *ipc.EmitSyncCollection //触发同步事件集合
}
// IChromium 组件接口
type IChromium interface {
IChromiumProc
IChromiumEvent
}
// TCEFChromium 组件
type TCEFChromium struct {
*lcl.TComponent
instance unsafe.Pointer
cfg *tCefChromiumConfig
emitLock *sync.Mutex
browserHandle types.HWND
widgetHandle types.HWND
renderHandle types.HWND
}
// NewChromium 创建一个新的 TCEFChromium
func NewChromium(owner lcl.IComponent, config *tCefChromiumConfig) IChromium {
m := new(TCEFChromium)
if config != nil {
m.cfg = config
} else {
m.cfg = NewChromiumConfig()
}
m.instance = unsafe.Pointer(_CEFChromium_Create(lcl.CheckPtr(owner), uintptr(unsafe.Pointer(m.cfg))))
m.emitLock = new(sync.Mutex)
m.initDefault()
return m
}
// 默认的初始配置
func (m *TCEFChromium) initDefault() {
//通过设置这些首选项,可以降低/避免WebRTC的IP泄漏
m.SetWebRTCIPHandlingPolicy(HpDisableNonProxiedUDP)
m.SetWebRTCMultipleRoutes(STATE_DISABLED)
m.SetWebRTCNonproxiedUDP(STATE_DISABLED)
}
// Instance 组件实例指针
func (m *TCEFChromium) Instance() uintptr {
return uintptr(m.instance)
}
// GetBrowserById 获取ICefBrowser
func (m *TCEFChromium) GetBrowserById(browserId int32) *ICefBrowser {
return &ICefBrowser{
browseId: browserId,
chromium: m.instance,
}
}
func (m *TCEFChromium) browseEmitJsOnEvent(browseId int32, frameId int64, name string, argumentList ipc.IArgumentList) ProcessMessageError {
data := argumentList.Package()
r1 := _CEFFrame_SendProcessMessage(browseId, frameId, name, PID_RENDER, int32(argumentList.Size()), uintptr(unsafe.Pointer(&data[0])), uintptr(len(data)))
return ProcessMessageError(r1)
}
// On 监听事件,事件驱动在Go中监听,JS中触发
func (m *TCEFChromium) On(name string, eventCallback ipc.EventCallback) {
if eventCallback == nil {
return
}
ipc.IPC.Browser().On(name, eventCallback)
}
// ExecuteJavaScript
// 执行JS代码
//
// code: js代码
//
// scriptURL: js脚本地址 默认about:blank
//
// startLine: js脚本启始执行行号
func (m *TCEFChromium) ExecuteJavaScript(code, scriptURL string, startLine int32) {
_CEFChromium_ExecuteJavaScript(uintptr(m.instance), code, scriptURL, startLine)
}
// Emit
// 触发JS监听的事件-异步执行
//
// EmitTarget 接收目标, nil:mainBrowser&mainFrame, 可传递browser和指定浏览器窗口,JS监听事件的接收
func (m *TCEFChromium) Emit(eventName string, args ipc.IArgumentList, target IEmitTarget) ProcessMessageError {
if eventName == "" {
return PMErr_NAME_IS_NULL
}
m.emitLock.Lock()
defer m.emitLock.Unlock()
var (
browseId int32
frameId int64
)
if args == nil {
args = ipc.NewArgumentList()
}
if target == nil {
bsr := m.Browser()
browseId = bsr.Identifier()
frameId = bsr.MainFrame().Id
} else {
browseId = target.GetBrowserId()
frameId = target.GetFrameId()
if m.GetBrowserById(browseId).GetFrameById(frameId) == nil {
return PMErr_NOT_FOUND_FRAME
}
}
var idx = args.Size()
args.SetInt32(idx, int32(Tm_Async))
args.SetInt32(idx+1, 0)
args.SetString(idx+2, eventName, true)
m.browseEmitJsOnEvent(browseId, frameId, ipc.Ln_IPC_GoEmitJS, args)
return PME_OK
}
// EmitAndCallback
// 触发JS监听的事件-异步执行-带回调
//
// EmitTarget 接收目标, nil = mainBrowser mainFrame
func (m *TCEFChromium) EmitAndCallback(eventName string, args ipc.IArgumentList, target IEmitTarget, callback ipc.IPCCallback) ProcessMessageError {
if eventName == "" {
return PMErr_NAME_IS_NULL
}
m.emitLock.Lock()
defer m.emitLock.Unlock()
var (
browseId int32
frameId int64
ipcId = executeJS.msgID.New()
idx = args.Size()
)
if args == nil {
args = ipc.NewArgumentList()
}
if target == nil {
bsr := m.Browser()
browseId = bsr.Identifier()
frameId = bsr.MainFrame().Id
} else {
browseId = target.GetBrowserId()
frameId = target.GetFrameId()
if m.GetBrowserById(browseId).GetFrameById(frameId) == nil {
return PMErr_NOT_FOUND_FRAME
}
}
args.SetInt32(idx, int32(Tm_Callback))
args.SetInt32(idx+1, ipcId)
args.SetString(idx+2, eventName, true)
executeJS.emitCallback.EmitCollection.Store(ipcId, callback)
m.browseEmitJsOnEvent(browseId, frameId, ipc.Ln_IPC_GoEmitJS, args)
return PME_OK
}
// EmitAndReturn
// 触发JS监听的事件-同步执行-阻塞UI主线程
//
// 使用不当会造成 UI线程 锁死,一搬不在与JS监听中使用,与其它子进程通信时使用
//
// EmitTarget 接收目标, nil = mainBrowser mainFrame
func (m *TCEFChromium) EmitAndReturn(eventName string, args ipc.IArgumentList, target IEmitTarget) (ipc.IIPCContext, ProcessMessageError) {
if eventName == "" {
return nil, PMErr_NAME_IS_NULL
}
m.emitLock.Lock()
defer m.emitLock.Unlock()
var (
browseId int32
frameId int64
ipcId = executeJS.msgID.New()
idx = args.Size()
)
if args == nil {
args = ipc.NewArgumentList()
}
if target == nil {
bsr := m.Browser()
browseId = bsr.Identifier()
frameId = bsr.MainFrame().Id
} else {
browseId = target.GetBrowserId()
frameId = target.GetFrameId()
if m.GetBrowserById(browseId).GetFrameById(frameId) == nil {
return nil, PMErr_NOT_FOUND_FRAME
}
}
args.SetInt32(idx, int32(Tm_Sync))
args.SetInt32(idx+1, ipcId)
args.SetString(idx+2, eventName, true)
var callback = func(emitAsync *ipc.EmitSyncCollection, ipcId int32) ipc.IIPCContext {
emitAsync.Mutex.Lock()
defer emitAsync.Mutex.Unlock()
var chn = make(chan ipc.IIPCContext)
var ret ipc.IIPCContext
emitAsync.EmitCollection.Store(ipcId, chn)
ret = <-chn //锁住当前线程
executeJS.emitSync.EmitCollection.Delete(ipcId)
return ret
}
m.browseEmitJsOnEvent(browseId, frameId, ipc.Ln_IPC_GoEmitJS, args)
return callback(executeJS.emitSync, ipcId), PME_OK
}
此差异已折叠。
此差异已折叠。
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
// energy 的错误消息
package cef
import (
. "github.com/energye/energy/consts"
)
// cefErrorMessage 错误信息描述-内部调用
func cefErrorMessage(code CEF_V8_EXCEPTION) string {
switch code {
case CVE_ERROR_OK:
return Empty
case CVE_ERROR_NOT_FOUND_FIELD:
return "field not found, or field undefined"
case CVE_ERROR_NOT_FOUND_FUNC:
return "function not found, or function undefined"
case CVE_ERROR_TYPE_NOT_SUPPORTED:
return "variable type is not supported. Only the variable type is supported [string int double bool null undefined]"
case CVE_ERROR_TYPE_CANNOT_CHANGE:
return "field type is common and cannot be changed to array、object、function"
case CVE_ERROR_TYPE_INVALID:
return "type is invalid"
case CVE_ERROR_GET_STRING_FAIL:
return "failed to get string"
case CVE_ERROR_GET_INT_FAIL:
return "fFailed to get int"
case CVE_ERROR_GET_DOUBLE_FAIL:
return "failed to get a double"
case CVE_ERROR_GET_BOOL_FAIL:
return "failed to get a bool"
case CVE_ERROR_GET_NULL_FAIL:
return "failed to get null"
case CVE_ERROR_GET_UNDEFINED_FAIL:
return "failed to get undefined"
case CVE_ERROR_FUNC_INVALID_P_L_9:
return "function is invalid, of an incorrect type, or has more than 9 arguments"
case CVE_ERROR_FUNC_IN_PAM:
return "input parameter type is incorrect. It can only be string int double Boolean"
case CVE_ERROR_FUNC_OUT_PAM:
return "parameter type is incorrect and can only be [string int double boolean]"
case CVE_ERROR_FUNC_GET_IN_PAM_STRING_FAIL:
return "failed to obtain a string value for the input parameter"
case CVE_ERROR_FUNC_GET_IN_PAM_INT_FAIL:
return "failed to obtain an int value for the input parameter"
case CVE_ERROR_FUNC_GET_IN_PAM_DOUBLE_FAIL:
return "entry failed to get a value of type double"
case CVE_ERROR_FUNC_GET_IN_PAM_BOOLEAN_FAIL:
return "failed to get a value of the Boolean type"
case CVE_ERROR_FUNC_GET_OUT_PAM_STRING_FAIL:
return "failed to obtain a string value for the output parameter"
case CVE_ERROR_FUNC_GET_OUT_PAM_INT_FAIL:
return "failed to obtain a value of type int"
case CVE_ERROR_FUNC_GET_OUT_PAM_DOUBLE_FAIL:
return "output parameter failed to get a value of type double"
case CVE_ERROR_FUNC_GET_OUT_PAM_BOOLEAN_FAIL:
return "failed to obtain a value of type Boolean"
case CVE_ERROR_FUNC_GET_OUT_PAM_CEFERROR_FAIL:
return "failed to obtain a value for the output parameter"
case CVE_ERROR_IPC_GET_BIND_FIELD_VALUE_FAIL:
return "IPC failed to get the binding value. Procedure"
default:
return "unknown error at runtime"
}
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
// CEF V8 上下文
package cef
import "unsafe"
// ICefV8Context
// 渲染进程创建时对V8Value创建
type ICefV8Context struct {
instance uintptr
ptr unsafe.Pointer
Browser *ICefBrowser
Frame *ICefFrame
Global *ICEFv8Value
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册