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

Update document annotations and add some examples

上级 0013bbd3
......@@ -24,9 +24,9 @@ func appOnContextCreated(browser *ICefBrowser, frame *ICefFrame, context *ICefV8
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
//bindRender.registerContextEvent() // TODO render bind
ipcRender.makeIPC(context) // render ipc make
makeProcess(browser, frame, context) // process make
}
// appMainRunCallback 应用运行 - 默认实现
......
......@@ -8,11 +8,11 @@
//
//----------------------------------------
// CEF + Energy 应用程序
// Package cef All CEF implementations of Energy in Go
package cef
import (
"github.com/energye/energy/v2/cef/internal/cef"
"github.com/energye/energy/v2/cef/process"
"github.com/energye/energy/v2/common/imports"
. "github.com/energye/energy/v2/consts"
......@@ -41,6 +41,8 @@ func NewApplication(disableRegisDefaultEvent ...bool) *TCEFApplication {
application.registerDefaultEvent()
}
application.initDefaultSettings()
// 将应用设置到内部实现
cef.SetApplication(application)
}
return application
}
......
......@@ -8,10 +8,9 @@
//
//----------------------------------------
// Package i18n 多语言资源
// 资源使用文件加载
// 文件名格式 locale.[lang].json | locale.[lang].ini => locale.en-US.json | locale.zh-CN.ini
// 默认 zh_CN
// Package i18n Multilingual resources
// Resource usage file loading
// File name format: locale.[lang].json | locale.[lang].ini => locale.en-US.json | locale.zh-CN.ini
package i18n
import (
......@@ -23,8 +22,6 @@ import (
"strings"
)
type ResType int8 // 资源加载方式
var (
currentLang consts.LANGUAGE
resources map[string]string // 资源-优先
......@@ -53,6 +50,10 @@ func SetLocalFS(localFS *embed.FS, localFSPath string) {
// 切换语言
// 默认先在内置FS中加载
func Switch(lang consts.LANGUAGE) {
if currentLang == lang {
// 如果当前语言和切换语言一样
return
}
currentLang = lang
resources = make(map[string]string, 0)
if lang == consts.LANGUAGE_zh_CN {
......
......@@ -66,6 +66,6 @@ func v8init() {
//ipc初始化
ipcInit()
//bind初始化
bindInit()
//bindInit()
}
}
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
// Package bind Energy has not been exported or added yet
package bind
import (
......
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
package cef
var application ICEFApplication
// ICEFApplication
// CEF 应用内部保留接口
type ICEFApplication interface {
SingleProcess() bool
}
func SetApplication(app ICEFApplication) {
if application == nil {
application = app
}
}
// Application
// 返回 IApplication
func Application() ICEFApplication {
return application
}
......@@ -15,6 +15,7 @@
package ipc
import (
"github.com/energye/energy/v2/cef/internal/cef"
"github.com/energye/energy/v2/cef/ipc/callback"
"github.com/energye/energy/v2/cef/ipc/context"
"github.com/energye/energy/v2/cef/ipc/target"
......@@ -95,7 +96,7 @@ func On(name string, fn any, options ...types.OnOptions) {
return
}
var isOn = false
if options != nil && len(options) > 0 {
if options != nil && len(options) > 0 && !cef.Application().SingleProcess() {
option := options[0]
if option.OnType == types.OtAll {
isOn = true
......
......@@ -16,6 +16,7 @@ import (
"github.com/energye/energy/v2/cef/internal/ipc"
"github.com/energye/energy/v2/cef/process"
"sync"
"time"
)
// ipc bind event name
......@@ -93,15 +94,19 @@ func ipcInit() {
emitHandler: &ipcEmitHandler{callbackList: make(map[int32]*ipcCallback)},
onHandler: &ipcOnHandler{callbackList: make(map[string]*ipcCallback)},
}
ipc.CreateBrowserIPC() // Go IPC browser
ipc.CreateRenderIPC(0, time.Now().UnixMicro()) // Go IPC render
} else {
if process.Args.IsMain() {
ipcBrowser = &ipcBrowserProcess{}
ipc.CreateBrowserIPC() // Go IPC browser
} else if process.Args.IsRender() {
ipcRender = &ipcRenderProcess{
syncChan: &ipc.SyncChan{},
emitHandler: &ipcEmitHandler{callbackList: make(map[int32]*ipcCallback)},
onHandler: &ipcOnHandler{callbackList: make(map[string]*ipcCallback)},
}
ipc.CreateRenderIPC(0, time.Now().UnixMicro()) // Go IPC render
}
}
}
......
......@@ -13,7 +13,6 @@
package cef
import (
"fmt"
"github.com/energye/energy/v2/common/imports"
"github.com/energye/golcl/lcl/api"
"unsafe"
......@@ -42,10 +41,7 @@ func WindowInfoAsWindowless(windowInfo, windowParent uintptr, windowName string)
// code: js code
// handler: 处理器, 根据本地函数名回调该处理器
func RegisterExtension(name, code string, handler *ICefV8Handler) {
if isInternalBind(name) {
return
}
registerExtension(fmt.Sprintf("%s/%s", internalV8Bind, name), code, handler)
registerExtension(name, code, handler)
}
func registerExtension(name, code string, handler *ICefV8Handler) {
......
......@@ -8,6 +8,7 @@
//
//----------------------------------------
// Package process Current process
package process
import "github.com/energye/energy/v2/cef/internal/process"
......
......@@ -15,6 +15,7 @@
// Go: 创建并绑定 ICefBinaryValue 对象名称: myobj
// JavaScript: let obj = new Uint8Array(window.myobj);
// console.log(obj)
package cef
import (
......
......@@ -9,6 +9,7 @@
//----------------------------------------
// CEF 回调事件实现
package cef
import (
......
......@@ -7,7 +7,6 @@
//
//----------------------------------------
// CEF 字典类型 DictionaryValueRef.New()
package cef
import (
......
......@@ -8,7 +8,6 @@
//
// ----------------------------------------
// CefDisplay
package cef
import (
......
......@@ -8,7 +8,6 @@
//
//----------------------------------------
// CEF下载项
package cef
import (
......
......@@ -8,7 +8,6 @@
//
// ----------------------------------------
// CEF Frame
package cef
import (
......
......@@ -8,7 +8,6 @@
//
//----------------------------------------
// CEF Image ImageRef.New
package cef
import (
......
......@@ -8,7 +8,6 @@
//
//----------------------------------------
// CEF 集合类型 ListValueRef.New
package cef
import (
......
......@@ -8,7 +8,6 @@
//
//----------------------------------------
// PDF 打印回调 PdfPrintCallbackRef.New
package cef
import (
......
......@@ -8,7 +8,6 @@
//
//----------------------------------------
//CEF PostDataElement PostDataElementRef.New
package cef
import (
......
......@@ -8,7 +8,6 @@
//
//----------------------------------------
// CEF PostData PostDataRef.New
package cef
import (
......
......@@ -8,7 +8,6 @@
//
//----------------------------------------
// PDF 打印回调 PdfPrintCallbackRef.New
package cef
import (
......
......@@ -8,7 +8,6 @@
//
//----------------------------------------
// PDF 打印回调 PdfPrintCallbackRef.New
package cef
import (
......
......@@ -8,7 +8,6 @@
//
//----------------------------------------
// PDF 打印回调 PdfPrintCallbackRef.New
package cef
import (
......
......@@ -8,7 +8,6 @@
//
//----------------------------------------
// CEF 进程消息 ProcessMessageRef.New()
package cef
import (
......
......@@ -8,7 +8,6 @@
//
//----------------------------------------
// cef -> energy 结构指定类型定义
package cef
import (
......
......@@ -11,6 +11,7 @@
// CEF v8 对象字段&值访问器(读取/写入) V8AccessorRef.New()
//
// ICefV8Value
package cef
import (
......
......@@ -9,6 +9,7 @@
//----------------------------------------
// v8 缓存释放时回调 V8ArrayBufferReleaseCallbackRef.New()
package cef
import (
......
......@@ -8,7 +8,6 @@
//
//----------------------------------------
// CEF V8 上下文
package cef
import (
......
......@@ -9,6 +9,7 @@
//----------------------------------------
//CEF v8 异常
package cef
import (
......
......@@ -9,6 +9,7 @@
//----------------------------------------
//CEF v8 执行函数拦截
package cef
import (
......
......@@ -13,6 +13,7 @@
// ICefV8Value
//
// TODO 未使用
package cef
import (
......
......@@ -11,6 +11,7 @@
// CEF v8 value V8所有类型
//
// ICefV8Value 创建和使用一搬在 v8context 上下文中使用
package cef
import (
......
......@@ -9,6 +9,7 @@
//----------------------------------------
// CEF Value 所有值类型 ValueRef.New
package cef
import (
......
......@@ -8,7 +8,6 @@
//
//----------------------------------------
// cef view
package cef
// Instance 实例
......
......@@ -8,9 +8,6 @@
//
//----------------------------------------
// cef window
//
// VF窗口组件
package cef
import (
......
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
// 基于IPC的字段数据绑定 - 主进程
package cef
import (
"fmt"
iterBind "github.com/energye/energy/v2/cef/internal/bind"
"github.com/energye/energy/v2/cef/internal/ipc"
"github.com/energye/energy/v2/cef/ipc/argument"
"github.com/energye/energy/v2/common"
"github.com/energye/energy/v2/pkgs/json"
"reflect"
"strings"
"sync"
)
var bindBrowser *bindBrowserProcess
type bindBrowserProcess struct {
bindObject json.JSONObject
bind *iterBind.V8bind
lock sync.Mutex
bindResultWG *sync.WaitGroup
}
func (m *bindBrowserProcess) objectFieldBind(object json.JSONObject, jsv iterBind.JSValue) {
names := strings.Split(jsv.Name(), ".")
if len(names) == 1 {
if jsv.IsObject() {
object.Set(jsv.Name(), json.NewJSONObject(nil))
} else if jsv.IsArray() {
object.Set(jsv.Name(), json.NewJSONArray(nil))
} else if jsv.IsFunction() {
fn := json.NewJSONObject(nil)
fn.Set("t", int(jsv.Type()))
fn.Set("p", jsv.Id())
object.Set(jsv.Name(), fn)
} else {
object.Set(jsv.Name(), jsv.Id())
}
} else {
name := names[len(names)-1]
var pObject = object
for i := 0; i < len(names)-1; i++ {
if pObject.IsObject() {
pObject = pObject.GetByKey(names[i])
} else {
pObject = pObject.JSONArray().GetByIndex(int(common.StrToInt32(names[i])))
}
}
if jsv.IsObject() {
if pObject.IsArray() {
pObject.JSONArray().Add(json.NewJSONObject(nil))
} else if pObject.IsObject() {
pObject.Set(name, json.NewJSONObject(nil))
}
} else if jsv.IsArray() {
if pObject.IsArray() {
pObject.JSONArray().Add(json.NewJSONArray(nil))
} else if pObject.IsObject() {
pObject.Set(name, json.NewJSONArray(nil))
}
} else if jsv.IsFunction() {
fn := json.NewJSONObject(nil)
fn.Set("t", int(jsv.Type()))
fn.Set("p", jsv.Id())
if pObject.IsArray() {
pObject.JSONArray().Add(fn)
} else if pObject.IsObject() {
pObject.Set(name, fn)
}
} else {
if pObject.IsObject() {
pObject.Set(name, jsv.Id())
} else if pObject.IsArray() {
pObject.JSONArray().Add(jsv.Id())
}
}
}
}
// registerFieldBindEvent
// 绑定字段IPC事件初始化
// 生成绑定数据结构
// 注册事件
func (m *bindBrowserProcess) registerFieldBindEvent() {
go iterBind.GetBinds(func(bind *iterBind.V8bind) {
m.bind = bind
var bindObject = json.NewJSONObject(nil)
fields := bind.FieldCollection()
for item := fields.Front(); item != nil; item = item.Next() {
jsv := bind.ElementToJSValue(item)
m.objectFieldBind(bindObject, jsv)
}
m.bindObject = bindObject
if m.bindResultWG != nil {
m.bindResultWG.Done()
}
fmt.Println("browser-bindObject-size:", m.bindObject.Size())
fmt.Println("browser-bindObject-json:", m.bindObject.ToJSONString())
})
// 注册事件
ipc.BrowserChan().AddCallback(func(channelId int64, argument argument.IList) bool {
if argument != nil {
name := argument.GetName()
fmt.Println("name", name)
if name == internalGetFieldBind {
// 发送绑定字段数据结构结果
go m.sendFieldBindResult(channelId)
return true
} else if name == internalGET {
// 获取绑定值
go m.getterBindValue(channelId, argument.GetData().(string))
return true
} else if name == internalSET {
go m.setterBindValue(channelId, argument)
return true
} else if name == internalCALL {
m.call(channelId, argument)
return true
}
}
return false
})
}
// call
// 调用绑定函数
func (m *bindBrowserProcess) call(channelId int64, argument argument.IList) {
if argument.JSON() != nil {
fmt.Println("call-argument", argument.JSON().ToJSONString())
}
}
// setterBindValue
// 设置绑定值
func (m *bindBrowserProcess) setterBindValue(channelId int64, argument argument.IList) {
if argument.JSON() != nil {
data := argument.JSON().JSONObject()
ptr := data.GetStringByKey("P")
p := uintptr(common.StrToInt64(ptr))
t := reflect.Kind(data.GetIntByKey("T"))
if jsv := m.bind.GetJSValue(p); jsv != nil {
if t == jsv.Type() && jsv.BindType() == iterBind.BtStatic {
jsv.SetValue(data.GetByKey("V").Data())
} else if jsv.BindType() == iterBind.BtDynamic {
jsv.SetValue(data.GetByKey("V").Data())
}
}
}
}
// getterBindValue
// 获取绑定值
func (m *bindBrowserProcess) getterBindValue(channelId int64, ptr string) {
fmt.Println("ptr:", ptr)
p := uintptr(common.StrToInt64(ptr))
jsv := m.bind.GetJSValue(p)
//发送返回结果
message := &argument.List{
Name: internalGETResult,
}
if jsv != nil {
bd := &iterBind.Data{
P: ptr,
T: jsv.Type(),
}
if data, ok := jsv.JSON().Data().(*reflect.Value); ok {
bd.V = data.Interface()
} else {
bd.V = jsv.JSON().Data()
}
message.Data = bd
}
ipc.BrowserChan().IPC().Send(channelId, message.Bytes())
message.Reset()
}
// sendFieldBindResult
// 发送绑定字段结果
func (m *bindBrowserProcess) sendFieldBindResult(channelId int64) {
m.lock.Lock()
defer m.lock.Unlock()
if m.bindObject == nil {
m.bindResultWG = new(sync.WaitGroup)
m.bindResultWG.Add(1)
m.bindResultWG.Wait()
m.bindResultWG = nil
}
message := &argument.List{
Name: internalGetFieldBindResult,
Data: m.bindObject.JsonData().ConvertToData(),
}
ipc.BrowserChan().IPC().Send(channelId, message.Bytes())
message.Reset()
}
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
// 基于IPC的字段数据绑定 - 渲染(子)进程
package cef
import (
"bytes"
"fmt"
"github.com/energye/energy/v2/pkgs/json"
"text/template"
)
// registerBindExtension
// 注册绑定JS扩展
func (m *bindRenderProcess) registerBindExtension(bindObject json.JSONObject) {
temp, err := template.New("v8bind").Parse(bindTemplate)
if err != nil {
panic(err)
}
var data = map[string]any{}
data["bind"] = internalBind
data["JSONObject"] = bindObject.ToJSONString()
var tempResult = &bytes.Buffer{}
err = temp.Execute(tempResult, data)
if err != nil {
panic(err)
}
//fmt.Println("tempResult:", tempResult.String())
registerExtension(fmt.Sprintf("%s/%s", internalV8Bind, internalBind), tempResult.String(), m.handler)
tempResult.Reset()
}
var bindTemplate = `let {{.bind}};
(function () {
const __energyBind = {
util: {
isObject(value) {
if (value && value.t) {
return false
}
return Object.prototype.toString.call(value) === '[object Object]'
},
isArray(value) {
if (value && value.t) {
return false
}
return Object.prototype.toString.call(value) === '[object Array]';
},
isProxy(value) {
if (value && value.t) {
return false
}
return Object.prototype.toString.call(value) === '[object Proxy]';
},
isFunction(value) {
if (!value) {
return false
}
return value.t === 19
}
},
createProxy(object) {
return new Proxy(object, __energyBind.handler);
},
handler: {
get(target, key, receiver) {
//console.log("GET target:", target, "key:", key, "value:", target[key], "receiver:", receiver);
let value = target[key];
if (!value) {
if (key === 'toJSON') {
//native function toJSON();
//let result = toJSON(target);
//return JSON.stringify(target);
return;
} else if (key === 'length') {
return target.length;
}
throw new Error("error " + key);
}
if (__energyBind.util.isObject(value) || __energyBind.util.isArray(value)) {
return __energyBind.createProxy(value);
} else if (__energyBind.util.isFunction(value)) {
return function (...arguments) {
// call
native function call();
let result = call(value.p.toString(), arguments);
return result;
}
}
// get
native function get();
let result = get(value.toString());
// console.log('native get result:', result);
return result;
// return Reflect.get(target, key, receiver);
},
set(target, key, newValue, receiver) {
let value = target[key];
if (!value) {
throw new Error("binding object does not allow extension of new fields. " + target + " - " + key);
} else if (__energyBind.util.isObject(value)) {
throw new Error("binding object cannot be assigned a value. " + target + " - " + key);
} else if (__energyBind.util.isFunction(value)) {
throw new Error("binding object functions cannot be assigned. " + target + " - " + key);
} else if (__energyBind.util.isArray(value)) {
throw new Error("binding object arrays cannot be assigned. " + target + " - " + key);
} else {
native function set();
set(value.toString(), newValue);
}
console.log("SET target:", target, "key:", key, "value:", value, "newValue:", newValue, "receiver:", receiver);
return true;
},
deleteProperty(target, key) {
throw new Error("binding object not allowed to be deleted. " + target + " - " + key);
},
isExtensible(target) {
throw new Error("binding object does not allow extension of new fields. " + target);
},
// defineProperty() {
// throw new Error("error defineProperty");
// },
preventExtensions() {
throw new Error("error preventExtensions");
},
setPrototypeOf(){
throw new Error("error setPrototypeOf");
}
}
}
{{.bind}} = __energyBind.createProxy({{.JSONObject}});
})();
`
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
// 基于IPC的字段数据绑定 - 渲染(子)进程
package cef
import (
"fmt"
iterBind "github.com/energye/energy/v2/cef/internal/bind"
"github.com/energye/energy/v2/cef/internal/ipc"
"github.com/energye/energy/v2/cef/ipc/argument"
"github.com/energye/energy/v2/pkgs/json"
"reflect"
"sync"
)
var bindRender *bindRenderProcess
type bindRenderProcess struct {
isInitBindIPC bool
handler *ICefV8Handler
syncChan *ipc.SyncChan
}
func (m *bindRenderProcess) registerContextEvent() {
if m.isInitBindIPC {
return
}
m.isInitBindIPC = true
ipc.RenderChan().AddCallback(func(channelId int64, argument argument.IList) bool {
if argument != nil {
//messageJSON := data.JSONObject()
//messageId := messageJSON.GetIntByKey(ipc_id)// messageId: 同步永远是1
//name := messageJSON.GetStringByKey(ipc_name)
//argumentList := messageJSON.GetArrayByKey(ipc_argumentList)
//if name == internalIPCJSExecuteGoSyncEventReplay {
// return true
//}
}
return false
})
}
// registerFieldBindResultEvent
// webkit 初始化获取并创建绑定字段和事件
func (m *bindRenderProcess) registerFieldBindResultEvent() {
var (
bindObject json.JSONObject
waitResult = new(sync.WaitGroup)
)
waitResult.Add(1)
// 注册绑定字段返回相关事件
ipc.RenderChan().AddCallback(func(channelId int64, argument argument.IList) bool {
if argument == nil {
return false
}
name := argument.GetName()
// 获取绑定字段数据结构消息
if name == internalGetFieldBindResult { // webkit
if argument.JSON() != nil {
bindObject = argument.JSON().JSONObject()
} else {
bindObject = json.NewJSONObject(nil)
}
waitResult.Done() //返回结果
return true
} else if name == internalGETResult { // getter
if argument.JSON() != nil {
m.syncChan.ResultSyncChan <- argument.JSON().JSONObject()
} else {
m.syncChan.ResultSyncChan <- json.NewJSONObject(nil)
}
return true
} else if name == internalSETResult { // setter
return true
}
return false
})
// 获取绑定字段数据结构
message := &argument.List{
Id: 1,
BId: ipc.RenderChan().BrowserId(),
Name: internalGetFieldBind,
}
//发送数据到主进程
ipc.RenderChan().IPC().Send(message.Bytes())
message.Reset()
// TODO VF 组件有问题
waitResult.Wait() //等待返回
fmt.Println("webkit-bindObject-size::", bindObject.Size())
fmt.Println("webkit-bindObject-ToJSONString::", bindObject.ToJSONString())
m.webKitMakeBind(bindObject) // render webkit bind make
bindObject.Free()
}
// webKitMakeBind
func (m *bindRenderProcess) webKitMakeBind(bindObject json.JSONObject) {
m.handler = V8HandlerRef.New()
m.handler.Execute(func(name string, object *ICefV8Value, arguments *TCefV8ValueArray, retVal *ResultV8Value, exception *ResultString) bool {
if ipc.RenderChan() != nil && arguments.Size() > 0 {
//renderIPC.ipc.Send()
fmt.Println("v8Handler.Execute", name, ipc.RenderChan(), arguments.Size(), arguments.Get(0).GetStringValue())
//获取绑定字段值
if name == internalGET {
m.getterBindValue(arguments, retVal)
return true
} else if name == internalSET {
m.setterBindValue(arguments, retVal)
return true
} else if name == internalCALL {
m.call(arguments, retVal)
return true
}
}
return false
})
// 注册绑定JS扩展
m.registerBindExtension(bindObject)
}
// call
// 调用绑定函数
func (m *bindRenderProcess) call(arguments *TCefV8ValueArray, retVal *ResultV8Value) {
if arguments == nil || arguments.Size() == 0 {
return
}
ptr := arguments.Get(0)
defer ptr.Free()
if !ptr.IsString() {
return
}
fmt.Println("call-ptr:", ptr.GetStringValue(), "size:", arguments.Size())
if arguments.Size() == 2 {
args := arguments.Get(1)
defer args.Free()
if !args.IsArray() {
return
}
fmt.Println("call-ptr:", ptr.GetStringValue(), "GetArrayLength:", args.GetArrayLength())
}
}
// setterBindValue
// 设置绑定值
func (m *bindRenderProcess) setterBindValue(arguments *TCefV8ValueArray, retVal *ResultV8Value) {
if arguments == nil || arguments.Size() != 2 {
return
}
ptr := arguments.Get(0)
defer ptr.Free()
if !ptr.IsString() {
return
}
newValue := arguments.Get(1)
defer newValue.Free()
bd := &iterBind.Data{}
if newValue.IsString() {
bd.T = reflect.String
bd.V = newValue.GetStringValue()
} else if newValue.IsInt() {
bd.T = reflect.Int
bd.V = newValue.GetIntValue()
} else if newValue.IsUInt() {
bd.T = reflect.Uint
bd.V = newValue.GetUIntValue()
} else if newValue.IsDouble() {
bd.T = reflect.Float64
bd.V = newValue.GetDoubleValue()
} else if newValue.IsBool() {
bd.T = reflect.Bool
bd.V = newValue.GetBoolValue()
} else {
// 暂时不支持复合类型赋值
return
}
bd.P = ptr.GetStringValue()
message := &argument.List{
Name: internalSET,
BId: ipc.RenderChan().BrowserId(),
Data: bd,
}
fmt.Println("setterBindValue-ptr:", string(message.Bytes()))
ipc.RenderChan().IPC().Send(message.Bytes())
message.Reset()
}
// getterBindValue
// 获取绑定值
func (m *bindRenderProcess) getterBindValue(arguments *TCefV8ValueArray, retVal *ResultV8Value) {
if arguments == nil || arguments.Size() != 1 {
return
}
m.syncChan.DelayWaiting()
ptr := arguments.Get(0)
defer ptr.Free()
if !ptr.IsString() {
return
}
message := &argument.List{
Name: internalGET,
BId: ipc.RenderChan().BrowserId(),
Data: ptr.GetStringValue(),
}
ipc.RenderChan().IPC().Send(message.Bytes())
message.Reset()
data := <-m.syncChan.ResultSyncChan
m.syncChan.Stop()
var resultJSON json.JSONObject
if data != nil {
resultJSON = data.(json.JSONObject)
}
fmt.Println("获取返回结果:", resultJSON.ToJSONString(), resultJSON.GetStringByKey("V"))
if resultJSON != nil && resultJSON.Size() > 0 {
if v := ValueConvert.BindDataToV8Value(resultJSON); v != nil {
retVal.SetResult(v)
return
}
}
}
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
// 基于IPC的字段数据绑定
package cef
import (
"github.com/energye/energy/v2/cef/internal/ipc"
"github.com/energye/energy/v2/cef/process"
"time"
)
const (
internalV8Bind = "v8"
internalGET = "get"
internalGETResult = "get_result"
internalSET = "set"
internalSETResult = "set_result"
internalCALL = "call"
internalCALLResult = "call_result"
internalJSON = "json"
internalJSONResult = "json_result"
)
var internalBind = "energy"
const (
internalGetFieldBind = "field_bind"
internalGetFieldBindResult = "field_bind_result"
)
// isInternalBind 内部字段不能使用
func isInternalBind(name string) bool {
return name == internalBind || name == internalV8Bind || name == internalGetFieldBind || name == internalGetFieldBindResult || name == internalGET ||
name == internalGETResult || name == internalSET || name == internalSETResult || name == internalCALL || name == internalCALLResult || name == internalJSON || name == internalJSONResult
}
// SetBindName 设置自定义绑定根对象名
func SetBindName(name string) {
internalBind = name
}
// bindInit 初始化
func bindInit() {
isSingleProcess := application.SingleProcess()
if isSingleProcess {
bindBrowser = &bindBrowserProcess{}
bindRender = &bindRenderProcess{syncChan: &ipc.SyncChan{}}
// TODO 单进程有些问题
ipc.CreateBrowserIPC() // Go IPC browser
ipc.CreateRenderIPC(0, time.Now().UnixMicro()) // Go IPC render
} else {
if process.Args.IsMain() {
bindBrowser = &bindBrowserProcess{}
ipc.CreateBrowserIPC() // Go IPC browser
} else if process.Args.IsRender() {
bindRender = &bindRenderProcess{syncChan: &ipc.SyncChan{}}
ipc.CreateRenderIPC(0, time.Now().UnixMicro()) // Go IPC render
}
}
}
......@@ -8,7 +8,6 @@
//
//----------------------------------------
// energy VF窗口组件
package cef
import (
......
......@@ -8,8 +8,6 @@
//
//----------------------------------------
// CEFWindowParent组件
// Windows
package cef
import (
......
......@@ -8,6 +8,7 @@
//
//----------------------------------------
// Package common CEF Util
package common
import (
......
......@@ -8,7 +8,6 @@
//
//----------------------------------------
// 当前系统登录用户目录
package common
import (
......
......@@ -8,6 +8,8 @@
//
//----------------------------------------
// Package imports Dynamic Library Import Based on LCL
// You can also import and add custom dynamic libraries here
package imports
import (
......
......@@ -9,6 +9,7 @@
//----------------------------------------
// CEF & LCL Color
package consts
import (
......
......@@ -8,6 +8,7 @@
//
//----------------------------------------
// Package consts CEF const
package consts
import (
......
......@@ -9,6 +9,7 @@
//----------------------------------------
// 键盘Key码
package consts
// Virtual Keys, Standard Set
......
......@@ -9,6 +9,7 @@
//----------------------------------------
// Windows 消息
package consts
// WM_NCHITTEST constants
......
......@@ -68,6 +68,7 @@ func main() {
cef.V8ContextRef.Current().Frame().VisitDom(visitor)
fmt.Println("visitor-browserId:", cef.V8ContextRef.Current().Browser().Identifier())
fmt.Println("visitor-frameId:", cef.V8ContextRef.Current().Frame().Identifier())
fmt.Println("visitor-frameId:", process.FrameId())
return process.FrameId()
// OtSub 仅子进程监听该事件
......
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
package main
import (
"embed"
"fmt"
"github.com/energye/energy/v2/cef"
"github.com/energye/energy/v2/cef/i18n"
"github.com/energye/energy/v2/cef/ipc"
"github.com/energye/energy/v2/common"
"github.com/energye/energy/v2/consts"
"github.com/energye/energy/v2/pkgs/assetserve"
)
//go:embed resources
var resources embed.FS
func main() {
//全局初始化 每个应用都必须调用的
cef.GlobalInit(nil, &resources)
//创建应用
cefApp := cef.NewApplication()
// 在这里设置i18n资源加载方式, 这里使用内置到exe方式
i18n.SetLocalFS(&resources, "resources")
// 默认使用中文
i18n.Switch(consts.LANGUAGE_zh_CN)
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "http://localhost:22022/i18n.html"
if common.IsLinux() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
}
cef.BrowserWindow.Config.Title = "Energy i18n"
//监听语言切换
// t: 1 中文, 2 英文
ipc.On("switch", func(t int) string {
// 在页面使用按钮点击事件触发语言切换监听
// 然后我们观察页面上的鼠标右键菜单 前进 后退
if t == 1 {
i18n.Switch(consts.LANGUAGE_zh_CN)
return string(consts.LANGUAGE_zh_CN)
} else if t == 2 {
i18n.Switch(consts.LANGUAGE_en_US)
return string(consts.LANGUAGE_en_US)
}
return ""
})
//在主进程启动成功之后执行
//在这里启动内置http服务
//内置http服务需要使用 go:embed resources 内置资源到执行程序中
cef.SetBrowserProcessStartAfterCallback(func(b bool) {
fmt.Println("主进程启动 创建一个内置http服务")
//通过内置http服务加载资源
server := assetserve.NewAssetsHttpServer()
server.PORT = 22022 //服务端口号
server.AssetsFSName = "resources" //必须设置目录名和资源文件夹同名
server.Assets = &resources
go server.StartHttpServer()
})
//运行应用
cef.Run(cefApp)
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>i18n</title>
<style>
button {
margin: 5px;
}
</style>
<script type="application/javascript">
function switchZHCN() {
ipc.emit("switch", [1],function (result){
clearMsg()
msg("当前:", result)
})
}
function switchENUS() {
ipc.emit("switch", [2], function (result) {
clearMsg()
msg("current:", result)
})
}
</script>
</head>
<body style="margin: 0px;padding: 0px;">
<p>
<h3 style="-webkit-app-region: drag;">i18n</h3></p>
<button onclick="switchZHCN()">切换中文</button>
<button onclick="switchENUS()">switchEN</button>
<p id="msgHtml"></p>
</body>
<script type="application/javascript">
let msgHtml = document.getElementById("msgHtml");
function msg(...vvv) {
let str = msgHtml.innerHTML;
for (let i = 0; i < vvv.length; i++) {
str = str + " " + vvv[i];
}
str += "<br>";
msgHtml.innerHTML = str;
}
function clearMsg() {
msgHtml.innerHTML = "";
}
</script>
</html>
\ No newline at end of file
{
"back": "custom-back",
"forward": "custom-forward"
}
\ No newline at end of file
{
"back": "自定义-后退",
"forward": "自定义-前进"
}
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>webkit-register</title>
<style>
button {
margin: 5px;
}
</style>
<script type="application/javascript">
function SetMyParam() {
test.myparam = document.getElementById("newvalue").value;
}
function GetMyParam() {
msg("GetMyParam", test.myparam);
}
</script>
</head>
<body style="margin: 0px;padding: 0px;">
<p>
<h3 style="-webkit-app-region: drag;">webkit-register</h3>
</p>
<input id="newvalue" value="new value"/>
<button onclick="SetMyParam()">Set myparam value</button>
<button onclick="GetMyParam()">Get myparam value</button>
<p id="msgHtml"></p>
</body>
<script type="application/javascript">
let msgHtml = document.getElementById("msgHtml");
function msg(...vvv) {
let str = msgHtml.innerHTML;
for (let i = 0; i < vvv.length; i++) {
str = str + " " + vvv[i];
}
str += "<br>";
msgHtml.innerHTML = str;
}
function clearMsg() {
msgHtml.innerHTML = "";
}
</script>
</html>
\ No newline at end of file
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
package main
import (
"embed"
"fmt"
"github.com/energye/energy/v2/cef"
"github.com/energye/energy/v2/common"
"github.com/energye/energy/v2/pkgs/assetserve"
)
//go:embed resources
var resources embed.FS
func main() {
//全局初始化 每个应用都必须调用的
cef.GlobalInit(nil, &resources)
//创建应用
cefApp := cef.NewApplication()
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "http://localhost:22022/webkit-register.html"
if common.IsLinux() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
}
cef.BrowserWindow.Config.Title = "Energy webkit-register"
// webkit 初始化时注册JS函数
// 使用 RegisterExtension
// V8Handler 接收执行时回调
cefApp.SetOnWebKitInitialized(func() {
var myparamValue string
v8Handler := cef.V8HandlerRef.New()
v8Handler.Execute(func(name string, object *cef.ICefV8Value, arguments *cef.TCefV8ValueArray, retVal *cef.ResultV8Value, exception *cef.ResultString) bool {
fmt.Println("v8Handler.Execute", name)
var result bool
if name == "GetMyParam" {
result = true
retVal.SetResult(cef.V8ValueRef.NewString(myparamValue))
} else if name == "SetMyParam" {
if arguments.Size() > 0 {
newValue := arguments.Get(0)
fmt.Println("value is string:", newValue.IsString())
fmt.Println("value:", newValue.GetStringValue())
myparamValue = newValue.GetStringValue()
newValue.Free()
}
result = true
}
return result
})
//注册js
var jsCode = `
let test;
if (!test) {
test = {};
}
(function () {
test.__defineGetter__('myparam', function () {
native function GetMyParam();
return GetMyParam();
});
test.__defineSetter__('myparam', function (b) {
native function SetMyParam();
if (b) SetMyParam(b);
});
})();
`
// 注册JS 和v8处理器
cef.RegisterExtension("v8/test", jsCode, v8Handler)
})
//在主进程启动成功之后执行
//在这里启动内置http服务
//内置http服务需要使用 go:embed resources 内置资源到执行程序中
cef.SetBrowserProcessStartAfterCallback(func(b bool) {
fmt.Println("主进程启动 创建一个内置http服务")
//通过内置http服务加载资源
server := assetserve.NewAssetsHttpServer()
server.PORT = 22022 //服务端口号
server.AssetsFSName = "resources" //必须设置目录名和资源文件夹同名
server.Assets = &resources
go server.StartHttpServer()
})
//运行应用
cef.Run(cefApp)
}
......@@ -8,8 +8,7 @@
//
//----------------------------------------
//简单的日志输出
// Package logger Simple log output
package logger
import (
......
......@@ -15,6 +15,7 @@
// 2. 编译时 使用 -ldflags "-s -w" 去除调试信息和符号
// 3. 使用 upx 工具压缩执行文件
// 最好是 2 和 3 配合使用
package assetserve
import (
......
......@@ -8,7 +8,7 @@
//
//----------------------------------------
// CEF & Go 类型映射
// Package types CEF & Go 类型映射
package types
import (
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册