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

Fixed Chinese input and gtk3 issues for linux packaging

上级 81f741a2
...@@ -63,9 +63,18 @@ func NewApplicationConfig() *tCefApplicationConfig { ...@@ -63,9 +63,18 @@ func NewApplicationConfig() *tCefApplicationConfig {
m.SetDisableZygote(true) m.SetDisableZygote(true)
m.SetCheckCEFFiles(false) m.SetCheckCEFFiles(false)
m.SetRemoteDebuggingPort(0) m.SetRemoteDebuggingPort(0)
m.SetExternalMessagePump(false)
m.SetMultiThreadedMessageLoop(true)
m.SetChromeRuntime(false) m.SetChromeRuntime(false)
//linux >= 107.xxx 版本以后,默认启用的GTK3,106及以前版本默认支持GTK2但无法正常输入中文
//顾强制使用GTK3方式,但又无法正常创建lcl组件到窗口中,该框架只对浏览器应用做封装
//所以初衷以浏览器应用建设为目标
if common.IsLinux() {
//linux平台默认设置为false,将启用 ViewsFrameworkBrowserWindow 窗口
m.SetExternalMessagePump(false)
m.SetMultiThreadedMessageLoop(false)
} else {
m.SetExternalMessagePump(false)
m.SetMultiThreadedMessageLoop(true)
}
return m return m
} }
......
...@@ -32,14 +32,6 @@ func NewCEFApplication(cfg *tCefApplicationConfig) *TCEFApplication { ...@@ -32,14 +32,6 @@ func NewCEFApplication(cfg *tCefApplicationConfig) *TCEFApplication {
cfg = NewApplicationConfig() cfg = NewApplicationConfig()
} }
cfg.framework() cfg.framework()
//linux >= 107.xxx 版本以后,默认不支持GTK2,同时GTK2又无法正常输入中文
//顾强制使用GTK3方式,但又无法正常创建lcl组件到窗口中,该框架只是对浏览器应用做封装
//所以尽量以正常使用为基准
if IsLinux() {
cfg.SetExternalMessagePump(false)
cfg.SetMultiThreadedMessageLoop(false)
}
m := new(TCEFApplication) m := new(TCEFApplication)
r1, _, _ := Proc(internale_CEFApplication_Create).Call(uintptr(unsafe.Pointer(cfg))) r1, _, _ := Proc(internale_CEFApplication_Create).Call(uintptr(unsafe.Pointer(cfg)))
m.instance = unsafe.Pointer(r1) m.instance = unsafe.Pointer(r1)
......
...@@ -35,24 +35,23 @@ type IBaseWindow interface { ...@@ -35,24 +35,23 @@ type IBaseWindow interface {
//BaseWindow 是一个基于chromium 和 lcl 的窗口组件 //BaseWindow 是一个基于chromium 和 lcl 的窗口组件
type BaseWindow struct { type BaseWindow struct {
*lcl.TForm // *lcl.TForm //
chromium IChromium // chromium IChromium //
windowParent ITCefWindow // windowParent ITCefWindow //
browserViewComponent *TCEFBrowserViewComponent // vFrameBrowserWindow *ViewsFrameworkBrowserWindow //基于CEF views framework窗口
windowComponent *TCEFWindowComponent // windowInfo *TCefWindowInfo //基于LCL窗口信息
windowInfo *TCefWindowInfo //窗口信息 windowId int32 //
windowId int32 // windowType WINDOW_TYPE //0:browser 1:devTools 2:viewSource 默认:0
windowType WINDOW_TYPE //0:browser 1:devTools 2:viewSource 默认:0 isClosing bool //
isClosing bool // canClose bool //
canClose bool // onResize []TNotifyEvent //
onResize []TNotifyEvent // onActivate []TNotifyEvent //
onActivate []TNotifyEvent // onShow []TNotifyEvent //
onShow []TNotifyEvent // onClose []TCloseEvent //
onClose []TCloseEvent // onCloseQuery []TCloseQueryEvent //
onCloseQuery []TCloseQueryEvent // onActivateAfter lcl.TNotifyEvent //
onActivateAfter lcl.TNotifyEvent // isFormCreate bool //是否创建完成 WindowForm
isFormCreate bool //是否创建完成 WindowForm isChromiumCreate bool //是否创建完成 Chromium
isChromiumCreate bool //是否创建完成 Chromium
} }
//创建一个带有 chromium 窗口 //创建一个带有 chromium 窗口
...@@ -67,6 +66,10 @@ func NewBrowserWindow(config *tCefChromiumConfig, defaultUrl string) *Window { ...@@ -67,6 +66,10 @@ func NewBrowserWindow(config *tCefChromiumConfig, defaultUrl string) *Window {
return window return window
} }
func (m *BaseWindow) Id() int32 {
return m.windowId
}
func (m *BaseWindow) Show() { func (m *BaseWindow) Show() {
m.TForm.Show() m.TForm.Show()
} }
......
...@@ -12,16 +12,21 @@ import ( ...@@ -12,16 +12,21 @@ import (
"github.com/energye/energy/common" "github.com/energye/energy/common"
) )
type viewsFrameBrowserWindowOnEventCallback func(event *BrowserEvent, window *ViewsFrameworkBrowserWindow)
type browserWindowOnEventCallback func(event *BrowserEvent, window *TCefWindowInfo)
type browserWindowAfterOnEventCallback func(window *TCefWindowInfo)
//创建主窗口指定的一些快捷配置属性 //创建主窗口指定的一些快捷配置属性
type browserConfig struct { type browserConfig struct {
DefaultUrl string //默认URL地址 DefaultUrl string //默认URL地址
Title string //窗口标题 Title string //窗口标题
Icon string //窗口图标 Icon string //窗口图标
Width int32 //窗口宽 Width int32 //窗口宽
Height int32 //窗口高 Height int32 //窗口高
chromiumConfig *tCefChromiumConfig //主窗体浏览器配置 chromiumConfig *tCefChromiumConfig //主窗体浏览器配置
browserWindowOnEventCallback func(browserEvent *BrowserEvent, window *TCefWindowInfo) //主窗口初始化回调 viewsFrameBrowserWindowOnEventCallback viewsFrameBrowserWindowOnEventCallback //主窗口初始化回调 - 基于CEF views framework窗口
browserWindowAfterOnEventCallback func(window *TCefWindowInfo) //主窗口初始化之后回调 browserWindowOnEventCallback browserWindowOnEventCallback //主窗口初始化回调 - 基于LCL窗口
browserWindowAfterOnEventCallback browserWindowAfterOnEventCallback //主窗口初始化之后回调
} }
//设置chromium配置 //设置chromium配置
...@@ -31,13 +36,26 @@ func (m *browserConfig) SetChromiumConfig(chromiumConfig *tCefChromiumConfig) { ...@@ -31,13 +36,26 @@ func (m *browserConfig) SetChromiumConfig(chromiumConfig *tCefChromiumConfig) {
} }
} }
func (m *browserConfig) setBrowserWindowInitOnEvent(fn func(event *BrowserEvent, browserWindow *TCefWindowInfo)) { //主窗口初始化回调 - 基于CEF views framework窗口
//
//该回调函数和基于LCL窗口回调是互斥的,默认情况只有一个会被回调
func (m *browserConfig) setViewsFrameBrowserWindowOnEventCallback(fn viewsFrameBrowserWindowOnEventCallback) {
if fn != nil && common.Args.IsMain() {
m.viewsFrameBrowserWindowOnEventCallback = fn
}
}
//主窗口初始化回调 - 基于LCL窗口
//
//该回调函数和基于CEF窗口回调是互斥的,默认情况只有一个会被回调
func (m *browserConfig) setBrowserWindowInitOnEvent(fn browserWindowOnEventCallback) {
if fn != nil && common.Args.IsMain() { if fn != nil && common.Args.IsMain() {
m.browserWindowOnEventCallback = fn m.browserWindowOnEventCallback = fn
} }
} }
func (m *browserConfig) setBrowserWindowInitAfterOnEvent(fn func(browserWindow *TCefWindowInfo)) { //主窗口初始化回调 - 基于LCL窗口
func (m *browserConfig) setBrowserWindowInitAfterOnEvent(fn browserWindowAfterOnEventCallback) {
if fn != nil && common.Args.IsMain() { if fn != nil && common.Args.IsMain() {
m.browserWindowAfterOnEventCallback = fn m.browserWindowAfterOnEventCallback = fn
} }
......
...@@ -18,6 +18,7 @@ import ( ...@@ -18,6 +18,7 @@ import (
) )
type TCEFBrowserViewComponent struct { type TCEFBrowserViewComponent struct {
lcl.IComponent
instance unsafe.Pointer instance unsafe.Pointer
} }
......
...@@ -98,7 +98,7 @@ type browserWindow struct { ...@@ -98,7 +98,7 @@ type browserWindow struct {
// //
// 主进程启动成功之后,将创建主窗口 mainBrowserWindow 是一个默认的主窗口 // 主进程启动成功之后,将创建主窗口 mainBrowserWindow 是一个默认的主窗口
// //
// externalMessagePump和multiThreadedMessageLoop是false时将使用RunMessageLoop,这对linux v107.xxx之后版本支持的更好 // externalMessagePump和multiThreadedMessageLoop是false时启用 ViewsFrameworkBrowserWindow 窗口
// //
// 在这里启动浏览器的主进程和子进程 // 在这里启动浏览器的主进程和子进程
func Run(cefApp *TCEFApplication) { func Run(cefApp *TCEFApplication) {
...@@ -179,24 +179,40 @@ func (m *browser) MainWindow() *TCefWindowInfo { ...@@ -179,24 +179,40 @@ func (m *browser) MainWindow() *TCefWindowInfo {
return m.mainWindow return m.mainWindow
} }
// 主窗口和chromium初始化时回调 // 基于CEF views framework窗口 - 主窗口和chromium初始化时回调
//
// 当使用ViewsFramework创建窗口后,我们无法使用lcl创建组件到窗口中
//
// ViewsFramework窗口主要解决在linux下gtk2和gtk3共存以及无法输入中文问题
//
// ViewsFramework窗口 和 LCL窗口同时只能存在一种
//
// event 浏览器事件
//
// views framework window 窗口信息对象
func (m *browser) SetViewFrameBrowserInit(fn viewsFrameBrowserWindowOnEventCallback) {
m.Config.setViewsFrameBrowserWindowOnEventCallback(fn)
}
// 基于LCL窗口 - 主窗口和chromium初始化时回调
// //
// 在这里可以对主窗体事件监听和属性设置,和主窗口上的子组件创建 // 在这里可以对主窗体事件监听和属性设置,和主窗口上的子组件创建
// //
// 如果想创建子窗口或带有browser的窗口最好在 SetBrowserInitAfter 回调函数中创建 // 如果想创建子窗口或带有browser的窗口最好在 SetBrowserInitAfter 回调函数中创建
// //
// event 浏览器事件 // event 浏览器事件
// mainBrowserWindow 窗口信息对象 //
func (m *browser) SetBrowserInit(fn func(event *BrowserEvent, browserWindow *TCefWindowInfo)) { // browserWindow 窗口信息对象
func (m *browser) SetBrowserInit(fn browserWindowOnEventCallback) {
m.Config.setBrowserWindowInitOnEvent(fn) m.Config.setBrowserWindowInitOnEvent(fn)
} }
// 主窗体和chromium初始后回调 // 基于LCL窗口 - 主窗体和chromium初始后回调
// //
// 在这里可以对主窗体属性设置、添加子窗口、带有browser的窗口和子组件创建 // 在这里可以对主窗体属性设置、添加子窗口、带有browser的窗口和子组件创建
// //
// mainBrowserWindow 窗口信息对象 // mainBrowserWindow 窗口信息对象
func (m *browser) SetBrowserInitAfter(fn func(browserWindow *TCefWindowInfo)) { func (m *browser) SetBrowserInitAfter(fn browserWindowAfterOnEventCallback) {
m.Config.setBrowserWindowInitAfterOnEvent(fn) m.Config.setBrowserWindowInitAfterOnEvent(fn)
} }
......
...@@ -10,17 +10,41 @@ package cef ...@@ -10,17 +10,41 @@ package cef
import ( import (
"fmt" "fmt"
"github.com/energye/energy/common"
"github.com/energye/energy/consts" "github.com/energye/energy/consts"
"github.com/energye/golcl/lcl" "github.com/energye/golcl/lcl"
) )
//基于CEF views framework窗口
//
//该窗口使用CEF内部实现,在linux下107.xx以后版本默认使用GTK3,但无法使用lcl组件集成到窗口中
//
//当创建应用配置时 MultiThreadedMessageLoop 和 ExternalMessagePump 属性同时为false(linux系统默认强制false)时启用ViewsFramework窗口
type ViewsFrameworkBrowserWindow struct { type ViewsFrameworkBrowserWindow struct {
component lcl.IComponent //
windowComponent *TCEFWindowComponent //
browserViewComponent *TCEFBrowserViewComponent //
}
func (m *ViewsFrameworkBrowserWindow) Component() lcl.IComponent {
return m.component
}
func (m *ViewsFrameworkBrowserWindow) WindowComponent() *TCEFWindowComponent {
return m.windowComponent
}
func (m *ViewsFrameworkBrowserWindow) BrowserViewComponent() *TCEFBrowserViewComponent {
return m.browserViewComponent
} }
func (m *browserWindow) appContextInitialized(app *TCEFApplication) { func (m *browserWindow) appContextInitialized(app *TCEFApplication) {
if !common.Args.IsMain() {
return
}
app.SetOnContextInitialized(func() { app.SetOnContextInitialized(func() {
fmt.Println("OnContextInitialized()") m.vFrameBrowserWindow = &ViewsFrameworkBrowserWindow{}
component := lcl.NewComponent(nil) m.vFrameBrowserWindow.component = lcl.NewComponent(nil)
if BrowserWindow.Config.chromiumConfig == nil { if BrowserWindow.Config.chromiumConfig == nil {
BrowserWindow.Config.chromiumConfig = NewChromiumConfig() BrowserWindow.Config.chromiumConfig = NewChromiumConfig()
BrowserWindow.Config.chromiumConfig.SetEnableMenu(true) BrowserWindow.Config.chromiumConfig.SetEnableMenu(true)
...@@ -28,43 +52,43 @@ func (m *browserWindow) appContextInitialized(app *TCEFApplication) { ...@@ -28,43 +52,43 @@ func (m *browserWindow) appContextInitialized(app *TCEFApplication) {
BrowserWindow.Config.chromiumConfig.SetEnableOpenUrlTab(true) BrowserWindow.Config.chromiumConfig.SetEnableOpenUrlTab(true)
BrowserWindow.Config.chromiumConfig.SetEnableWindowPopup(true) BrowserWindow.Config.chromiumConfig.SetEnableWindowPopup(true)
} }
m.chromium = NewChromium(component, BrowserWindow.Config.chromiumConfig) m.chromium = NewChromium(m.vFrameBrowserWindow.component, BrowserWindow.Config.chromiumConfig)
m.chromium.SetEnableMultiBrowserMode(true) m.chromium.SetEnableMultiBrowserMode(true)
m.browserViewComponent = NewBrowserViewComponent(component) m.vFrameBrowserWindow.browserViewComponent = NewBrowserViewComponent(m.vFrameBrowserWindow.component)
m.windowComponent = NewWindowComponent(component) m.vFrameBrowserWindow.windowComponent = NewWindowComponent(m.vFrameBrowserWindow.component)
m.chromium.SetOnBeforePopup(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, beforePopupInfo *BeforePopupInfo, client *ICefClient, noJavascriptAccess *bool) bool { m.chromium.SetOnBeforePopup(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, beforePopupInfo *BeforePopupInfo, client *ICefClient, noJavascriptAccess *bool) bool {
fmt.Println("OnBeforePopup TargetUrl:", beforePopupInfo.TargetUrl) fmt.Println("OnBeforePopup TargetUrl:", beforePopupInfo.TargetUrl)
return false return false
}) })
m.windowComponent.SetOnWindowCreated(func(sender lcl.IObject, window *ICefWindow) { m.vFrameBrowserWindow.windowComponent.SetOnWindowCreated(func(sender lcl.IObject, window *ICefWindow) {
if m.chromium.CreateBrowserByBrowserViewComponent(BrowserWindow.Config.DefaultUrl, m.browserViewComponent) { if m.chromium.CreateBrowserByBrowserViewComponent(BrowserWindow.Config.DefaultUrl, m.vFrameBrowserWindow.browserViewComponent) {
m.windowComponent.AddChildView(m.browserViewComponent) m.vFrameBrowserWindow.windowComponent.AddChildView(m.vFrameBrowserWindow.browserViewComponent)
m.windowComponent.SetTitle(BrowserWindow.Config.Title) m.vFrameBrowserWindow.windowComponent.SetTitle(BrowserWindow.Config.Title)
window.CenterWindow(NewCefSize(BrowserWindow.Config.Width, BrowserWindow.Config.Height)) window.CenterWindow(NewCefSize(BrowserWindow.Config.Width, BrowserWindow.Config.Height))
m.browserViewComponent.RequestFocus() m.vFrameBrowserWindow.browserViewComponent.RequestFocus()
if BrowserWindow.Config.Icon != "" { if BrowserWindow.Config.Icon != "" {
window.SetWindowAppIconFS(1, BrowserWindow.Config.Icon) window.SetWindowAppIconFS(1, BrowserWindow.Config.Icon)
} }
if BrowserWindow.Config.browserWindowOnEventCallback != nil { if BrowserWindow.Config.viewsFrameBrowserWindowOnEventCallback != nil {
BrowserWindow.browserEvent.chromium = m.chromium BrowserWindow.browserEvent.chromium = m.chromium
BrowserWindow.Config.browserWindowOnEventCallback(BrowserWindow.browserEvent, m.windowInfo) BrowserWindow.Config.viewsFrameBrowserWindowOnEventCallback(BrowserWindow.browserEvent, m.vFrameBrowserWindow)
} }
window.Show() window.Show()
} }
}) })
m.windowComponent.SetOnCanClose(func(sender lcl.IObject, window *ICefWindow, aResult *bool) { m.vFrameBrowserWindow.windowComponent.SetOnCanClose(func(sender lcl.IObject, window *ICefWindow, aResult *bool) {
fmt.Println("OnCanClose") fmt.Println("OnCanClose")
*aResult = true *aResult = true
app.QuitMessageLoop() app.QuitMessageLoop()
}) })
m.windowComponent.SetOnGetInitialBounds(func(sender lcl.IObject, window *ICefWindow, aResult *TCefRect) { m.vFrameBrowserWindow.windowComponent.SetOnGetInitialBounds(func(sender lcl.IObject, window *ICefWindow, aResult *TCefRect) {
fmt.Println("OnGetInitialBounds") fmt.Println("OnGetInitialBounds")
}) })
m.windowComponent.SetOnGetInitialShowState(func(sender lcl.IObject, window *ICefWindow, aResult *consts.TCefShowState) { m.vFrameBrowserWindow.windowComponent.SetOnGetInitialShowState(func(sender lcl.IObject, window *ICefWindow, aResult *consts.TCefShowState) {
fmt.Println("OnGetInitialShowState", *aResult) fmt.Println("OnGetInitialShowState", *aResult)
}) })
m.windowComponent.CreateTopLevelWindow() m.vFrameBrowserWindow.windowComponent.CreateTopLevelWindow()
}) })
} }
...@@ -20,6 +20,7 @@ import ( ...@@ -20,6 +20,7 @@ import (
) )
type TCEFWindowComponent struct { type TCEFWindowComponent struct {
lcl.IComponent
instance unsafe.Pointer instance unsafe.Pointer
} }
......
...@@ -117,10 +117,6 @@ func (m *TCefWindowInfo) Maximize() { ...@@ -117,10 +117,6 @@ func (m *TCefWindowInfo) Maximize() {
}) })
} }
func (m *TCefWindowInfo) WindowId() int32 {
return m.Window.windowId
}
// 关闭窗口-在ui线程中执行 // 关闭窗口-在ui线程中执行
func (m *TCefWindowInfo) Close() { func (m *TCefWindowInfo) Close() {
BrowserWindow.uiLock.Lock() BrowserWindow.uiLock.Lock()
...@@ -131,7 +127,7 @@ func (m *TCefWindowInfo) Close() { ...@@ -131,7 +127,7 @@ func (m *TCefWindowInfo) Close() {
return return
} }
if m.Window == nil { if m.Window == nil {
logger.Error("关闭浏览器 Form 为空 WindowId:", m.WindowId()) logger.Error("关闭浏览器 Window 为空")
return return
} }
if common.IsDarwin() { if common.IsDarwin() {
......
...@@ -21,7 +21,16 @@ func main() { ...@@ -21,7 +21,16 @@ func main() {
//指定一个URL地址,或本地html文件目录 //指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.DefaultUrl = "http://localhost:22022/index.html" cef.BrowserWindow.Config.DefaultUrl = "http://localhost:22022/index.html"
cef.BrowserWindow.Config.Icon = "resources/icon.png" cef.BrowserWindow.Config.Icon = "resources/icon.png"
cef.BrowserWindow.SetViewFrameBrowserInit(func(event *cef.BrowserEvent, window *cef.ViewsFrameworkBrowserWindow) {
fmt.Println("cef.BrowserWindow.SetViewFrameBrowserInit", window)
fmt.Printf("%+v\n", window)
})
cef.BrowserWindow.SetBrowserInit(func(event *cef.BrowserEvent, window *cef.TCefWindowInfo) {
fmt.Println("cef.BrowserWindow.SetBrowserInit", window)
fmt.Printf("%+v\n", window)
})
//在主进程启动成功之后执行 //在主进程启动成功之后执行
//在这里启动内置http服务 //在这里启动内置http服务
//内置http服务需要使用 go:embed resources 内置资源到执行程序中 //内置http服务需要使用 go:embed resources 内置资源到执行程序中
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册