...
 
Commits (54)
    https://gitcode.net/energye/energy/-/commit/bd96174e73be285cd166c07637fd072746817da0 U: .gitattributes 2023-07-19T20:06:52+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/12338f77217eca9c7cbd9cb9cfb03e5d61d0b96a A: windows demo custom-browser-create 2023-07-20T10:00:08+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/8cd155e107ba4145ba8310b2b97e3435f03e6ecb U: demo msgbox 2023-07-20T12:05:02+08:00 yanghy snxamdf@126.com https://gitcode.net/energye/energy/-/commit/69e2bd9cba7c1786634658de5a366671351d783c U: liblclbinres v1.0.1 2023-07-20T15:00:46+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/bfe5a85f155773a8ff3a47c8d2ae786473bd3859 A: gtk2 support for CEF 106.1.1 2023-07-20T17:54:49+08:00 yanghy snxamdf@126.com https://gitcode.net/energye/energy/-/commit/d540b82c39e69c912513859d4c373536e1c5f90e U: demos, ui use gtk3, IconFS = xxx.png, other IconFS = xxx.ico 2023-07-20T18:04:23+08:00 yanghy snxamdf@126.com https://gitcode.net/energye/energy/-/commit/d031f81689fc625daf109f02cb91c32eaf279308 Fix: aux-viewsource, linux 2023-07-20T18:06:26+08:00 yanghy snxamdf@126.com https://gitcode.net/energye/energy/-/commit/58a23467bf6b49e7a7398c1c2175048af0021672 A: TForm WM Message 2023-07-20T19:52:58+08:00 yanghy snxamdf@126.com https://gitcode.net/energye/energy/-/commit/fafbc4a2d9e5bcefeb70efa369e682945f6b505a A: TForm WM Message - > NotifyMoveOrResizeStarted 2023-07-20T22:35:49+08:00 yanghy snxamdf@126.com https://gitcode.net/energye/energy/-/commit/3d19c473be29b839e4191345c92a6753ad2a3a94 U: demo test 2023-07-20T22:37:36+08:00 yanghy snxamdf@126.com https://gitcode.net/energye/energy/-/commit/83e7362b15fbcf98719475a10517e2978585fc1b U: on message struct 2023-07-21T09:37:21+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/605cd9a0961cdc3733557f1f26309c8e8dfd5bb2 U: on message struct 2023-07-21T09:42:03+08:00 yanghy snxamdf@126.com https://gitcode.net/energye/energy/-/commit/bf42bf9eedb89095c6c18d4209e6e0e543372b95 A: on message paint 2023-07-21T09:56:28+08:00 yanghy snxamdf@126.com https://gitcode.net/energye/energy/-/commit/da36ecb5cb55c4e36b6f898dd3731b035cb174a5 U: LCL CloseBrowserWindow RunOnMainThread 2023-07-21T10:16:51+08:00 yanghy snxamdf@126.com https://gitcode.net/energye/energy/-/commit/790b33d57d5cff5fdd91888da7372ee15910b21e U: demo context-menu 2023-07-21T10:17:33+08:00 yanghy snxamdf@126.com https://gitcode.net/energye/energy/-/commit/84e506f90dfe3d71d8904c3da86084a002ab4f3a U: remove CustomWidgetSetFinalization 2023-07-21T10:25:06+08:00 yanghy snxamdf@126.com https://gitcode.net/energye/energy/-/commit/625b4fec0ecc96d76c04b1a53209ae79d4032f53 U: energy command line, support linux select gtk2 or gtk3 framework 2023-07-21T12:24:08+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/8f05acb8608bd2f293f4c560da60dd5792abbdd7 A: energy command line, Set energy framework development environment 2023-07-21T13:01:05+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/37a3da8f26b6cd718120856f887c180714505d7a A: energy command line, Set energy framework development environment 2023-07-21T14:03:33+08:00 yanghy snxamdf@126.com https://gitcode.net/energye/energy/-/commit/d28c9e5527beaaf7e861bb5f3edb066ed3ddbc6e U: gen libbin 2023-07-21T18:27:51+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/41be5483f2826e9357f25979cab26eda7cb0eeb5 U: tempdll README.md 2023-07-21T19:07:42+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/82a4036352be6173cc27921e6dc2f39b6935299f U: demo liblcl autoupdate , linux lcl widget init 2023-07-22T09:12:53+08:00 yanghy snxamdf@126.com https://gitcode.net/energye/energy/-/commit/45921e9fe42899f8d8efe79f69a95bb0f3981136 A: open tab url callback event 2023-07-23T00:04:20+08:00 杨红岩 snxamdf@126.com Fix: bugs U: Reasonably modify the CEF event logic https://gitcode.net/energye/energy/-/commit/150e6ad5b4960fbe323709a4bec8574eb06bfba5 U: context-menu 2023-07-23T00:08:18+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/a0506ff73062eeddd969c8f574a4f351c9e321c9 U: chromium context-menu-command callback 2023-07-23T00:13:38+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/15d71fe2548af2f804c705e7721bac7cf4bd6924 U: chromium context-menu-command callback 2023-07-23T00:15:35+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/5bd100bd27c61ee60f72e56a9ffdc246f595be16 U: window state 2023-07-23T17:42:29+08:00 杨红岩 snxamdf@126.com A: default window attribute configuration https://gitcode.net/energye/energy/-/commit/43deb13e679efb43d7ef51acf8ac023c2413f680 U: window state 2023-07-23T21:15:32+08:00 杨红岩 snxamdf@126.com A: default window attribute configuration https://gitcode.net/energye/energy/-/commit/c9f6cabe59d1c56ae25a11b6741276db9db755ef U: demo frameless, fullscreen 2023-07-23T21:16:11+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/2493d227e63b58f98eff61df8f59222b428f41d9 U: demo window state 2023-07-23T21:16:29+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/dc3baa6252bdc639ca907950e735721249ae3b51 U: demo window state 2023-07-23T21:17:09+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/cdfbe537404ce5418286cd37ccf2e1844a63bdcc U: browser window, full screen 2023-07-23T22:17:50+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/ea6717752a139e2abd40560dc486004c0d73d38f U: demo frameless 2023-07-23T22:18:20+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/c915164a7297d69cfe2a1bf4e49435cb7c23c189 A: window, full screen model, add common attributes 2023-07-23T22:46:34+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/a194a6167ff594a97ffcee6352f4a5f274a4a67c U: demo frameless 2023-07-23T22:47:28+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/48ed65c517b9c619a415a67ff020fdbe0342f6c4 Fix: v8value bug, string value error 2023-07-24T18:21:25+08:00 yanghy snxamdf@126.com https://gitcode.net/energye/energy/-/commit/e5d710b5e79654d8945cd15330e45a23b91fae70 Fix: potential problem, proc api return string error 2023-07-24T19:44:25+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/0c24eb7e3c76efb6cf80cdca718c806913a6f371 U: Optimize custom window drag and drop creation logic 2023-07-25T09:12:28+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/34797ee83493ab361c96b0c928848b7761c5a2aa U: demo popup-sub-window elliptic 2023-07-25T09:14:44+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/7604d7f9877595e85868b5cd5ac7d4f83f6660dc U: demo popup-sub-window elliptic 2023-07-25T09:37:34+08:00 yanghy snxamdf@126.com https://gitcode.net/energye/energy/-/commit/613c1bb9e9076d7276ae4822c044e9670417bcac U: demo scheme 2023-07-25T09:43:42+08:00 yanghy snxamdf@126.com https://gitcode.net/energye/energy/-/commit/2c9a525e5118b322bebd0e6c1e2839c4494f0855 Fix: Multiple display window centering issue 2023-07-25T12:36:51+08:00 杨红岩 snxamdf@126.com A: get screen info https://gitcode.net/energye/energy/-/commit/f05d3df3983250d200edccd5e50638dfd92daf33 Fix: Multiple display window centering issue 2023-07-25T12:37:52+08:00 杨红岩 snxamdf@126.com A: demo screen https://gitcode.net/energye/energy/-/commit/12acb7e1b0d20ef1e895df3a3af923da67fcdd26 A: displayRef proc api 2023-07-25T16:59:40+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/5cebde59e3655af2353ca72ebd86630d7caef692 A: Window IScreen 2023-07-25T18:06:54+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/d068ef38ca7f2344ce1d3f7f13127aca3002f2de A: demo Window IScreen 2023-07-25T18:07:26+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/561c42b1236273cdf7ab120679d6ef36dc035e2f U: Return value(float32) method 2023-07-25T18:12:07+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/2559feaee93e8952ba9b1b1bd5a8548b644bee8b U: demo main-browser-window 2023-07-25T18:41:16+08:00 yanghy snxamdf@126.com https://gitcode.net/energye/energy/-/commit/6c601b109ada2df46b6d6ecc0052602a2e2926f6 U: liblclbinres v1.0.2 2023-07-25T22:40:01+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/cd35a0df4dc8c3eacea713922cee94e307a7ac27 U: add get energy env command [energy env .] 2023-07-26T11:13:45+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/abde5bf2f0e55bd335fca6918b84132b85156fcd A: add demo build-examples, build examples exe to dist 2023-07-26T12:23:34+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/ec68724049deeb199706b126afcc763ed18ebfeb U: examples, build 2023-07-26T12:55:54+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/63973b360836252aa523f253d9d11fd1aec82ef8 U: examples, build 2023-07-26T13:31:18+08:00 杨红岩 snxamdf@126.com https://gitcode.net/energye/energy/-/commit/9b6525b16bad633d17abbc5819511674f0d3be42 U: examples, build 2023-07-26T13:48:59+08:00 杨红岩 snxamdf@126.com
*.pas linguist-language=go
*.inc linguist-language=go
*.h linguist-language=go
*.html linguist-language=go
\ No newline at end of file
*.html linguist-language=go
*.m linguist-language=go
\ No newline at end of file
......@@ -123,3 +123,5 @@ rsrc
bytes.txt
*.icns
icons.iconset/
dist
......@@ -26,7 +26,6 @@ func appOnContextCreated(browser *ICefBrowser, frame *ICefFrame, context *ICefV8
ipcRender.registerGoSyncReplayEvent() // render ipc
ipcRender.makeIPC(context) // render ipc make
makeProcess(browser, frame, context) // process make
dragExtensionJS(frame) // drag extension
}
// appMainRunCallback 应用运行 - 默认实现
......
......@@ -22,6 +22,7 @@ import (
"github.com/energye/energy/v2/types"
"github.com/energye/golcl/lcl/api"
"path"
"strings"
"unsafe"
)
......@@ -39,14 +40,54 @@ func (m *TCEFApplication) SetObjectRootName(name string) {
//imports.Proc(CEFV8ValueRef_SetObjectRootName).Call(api.PascalStr(internalObjectRootName))
}
func (m *TCEFApplication) IsUIWin32() bool {
return m.ui == UitWin32
}
func (m *TCEFApplication) IsUICocoa() bool {
return m.ui == UitCocoa
}
func (m *TCEFApplication) IsUIGtk2() bool {
return m.ui == UitGtk2
}
func (m *TCEFApplication) IsUIGtk3() bool {
return m.ui == UitGtk3
}
//initDefaultSettings 初始 energy 默认设置
func (m *TCEFApplication) initDefaultSettings() {
if common.IsWindows() {
m.ui = UitWin32
} else if common.IsDarwin() {
m.ui = UitCocoa
} else if common.IsLinux() {
cefVersion := strings.Split(m.LibCefVersion(), ".")
if len(cefVersion) > 0 {
major := common.StrToInt32(cefVersion[0])
// cef version <= 106.1.1 default use gtk2
if major <= 106 {
m.ui = UitGtk2
} else {
// cef version > 106.1.1 default use gtk3
m.ui = UitGtk3
}
} else {
// default use gtk3
m.ui = UitGtk3
}
} else {
panic("Unsupported system, currently only supports Windows, Mac OS, and Linux")
}
if m.FrameworkDirPath() == "" {
lp := common.LibPath()
if lp != "" {
m.SetFrameworkDirPath(lp)
}
}
m.SetLocale(LANGUAGE_zh_CN)
m.SetLogSeverity(LOGSEVERITY_DISABLE)
m.SetEnablePrintPreview(true)
......@@ -54,10 +95,16 @@ func (m *TCEFApplication) initDefaultSettings() {
// ViewsFrameworkBrowserWindow 简称(VF)窗口组件, 同时支持 Windows/Linux/MacOSX
// LCL 窗口组件,同时支持 Windows/MacOSX, CEF版本<=106.xx时支持GTK2, CEF版本 >= 107.xx时默认开启 GTK3 且不支持 GTK2 和 LCL提供的各种组件
if common.IsLinux() { // Linux => (VF)View Framework 窗口
// Linux CEF >= 107.xxx 版本以后,默认启用的GTK3,106及以前版本默认支持GTK2但无法正常输入中文
// Linux平台默认设置为false,将启用 ViewsFrameworkBrowserWindow 窗口
m.SetExternalMessagePump(false)
m.SetMultiThreadedMessageLoop(false)
if m.IsUIGtk3() {
// Linux CEF >= 107.xxx 版本以后,默认启用的GTK3,106及以前版本默认支持GTK2但无法正常输入中文
// Linux 默认设置为false,将启用 ViewsFrameworkBrowserWindow 窗口
m.SetExternalMessagePump(false)
m.SetMultiThreadedMessageLoop(false)
} else if m.IsUIGtk2() {
// GTK2 默认支持LCL,但还未解决无法输入中文问题
m.SetExternalMessagePump(false)
m.SetMultiThreadedMessageLoop(true)
}
// 这是一个解决“GPU不可用错误”问题的方法 linux
// https://bitbucket.org/chromiumembedded/cef/issues/2964/gpu-is-not-usable-error-during-cef
m.SetDisableZygote(true)
......@@ -74,36 +121,10 @@ func (m *TCEFApplication) initDefaultSettings() {
m.SetExternalMessagePump(false)
m.SetMultiThreadedMessageLoop(true)
}
m.SetEnableWebkitAppRegion(true)
m.SetEnableWebkitAppRegionDClk(true)
}
/*** 自定义属性 ***/
// EnableWebkitAppRegion
// html元素中设置css属性 [-webkit-app-region | --webkit-app-region]: drag/no-drag 是否允许拖拽区域 default: true
func (m *TCEFApplication) EnableWebkitAppRegion() bool {
return m.enableWebkitAppRegion
}
// SetEnableWebkitAppRegion
// 设置html元素中设置css属性 [-webkit-app-region | --webkit-app-region]: drag/no-drag 是否允许拖拽区域 default: true
func (m *TCEFApplication) SetEnableWebkitAppRegion(value bool) {
m.enableWebkitAppRegion = value
}
// EnableWebkitAppRegionDClk
// 拖拽区域是否启用标题栏双击最大化和还原 default: true
func (m *TCEFApplication) EnableWebkitAppRegionDClk() bool {
return m.enableWebkitAppRegionDClk
}
// SetEnableWebkitAppRegionDClk
// 设置拖拽区域是否启用标题栏双击最大化和还原 default: true
func (m *TCEFApplication) SetEnableWebkitAppRegionDClk(value bool) {
m.enableWebkitAppRegionDClk = value
}
/*** 设置 TCefSettings (cef_settings_t) 属性 ***/
func (m *TCEFApplication) NoSandbox() bool {
......@@ -819,10 +840,9 @@ func (m *TCEFApplication) SetDevToolsProtocolLogFile(value string) {
imports.Proc(def.CEFAppConfig_SetDevToolsProtocolLogFile).Call(api.PascalStr(value))
}
func (m *TCEFApplication) ForcedDeviceScaleFactor() float32 { //single
var result uintptr
func (m *TCEFApplication) ForcedDeviceScaleFactor() (result float32) { //single
imports.Proc(def.CEFAppConfig_ForcedDeviceScaleFactor).Call(uintptr(unsafe.Pointer(&result)))
return *(*float32)(unsafe.Pointer(result))
return
}
func (m *TCEFApplication) SetForcedDeviceScaleFactor(value float32) { //single
......@@ -1090,10 +1110,9 @@ func (m *TCEFApplication) SetReRaiseExceptions(value bool) {
imports.Proc(def.CEFAppConfig_SetReRaiseExceptions).Call(api.PascalBool(value))
}
func (m *TCEFApplication) DeviceScaleFactor() float32 {
var result uintptr
func (m *TCEFApplication) DeviceScaleFactor() (result float32) {
imports.Proc(def.CEFAppConfig_DeviceScaleFactor).Call(uintptr(unsafe.Pointer(&result)))
return *(*float32)(unsafe.Pointer(result))
return
}
func (m *TCEFApplication) LocalesRequired() string {
......
......@@ -67,10 +67,8 @@ func Run(app *TCEFApplication) {
// 启动主进程
success := app.StartMainProcess()
if success {
//if !consts.IsMessageLoop {
//LCL -> Linux 必须在主进程启动之后初始化组件
lclwidget.CustomWidgetSetInitialization()
//}
// 主进程启动成功之后回调
if browserProcessStartAfterCallback != nil {
browserProcessStartAfterCallback(success)
......@@ -87,7 +85,7 @@ func Run(app *TCEFApplication) {
}
// LCL窗口
lcl.RunApp(&BrowserWindow.mainBrowserWindow)
lclwidget.CustomWidgetSetFinalization()
//lclwidget.CustomWidgetSetFinalization()
}
}
}
......
......@@ -27,9 +27,8 @@ var application *TCEFApplication
// TCEFApplication CEF应用对象
type TCEFApplication struct {
instance unsafe.Pointer
enableWebkitAppRegion bool
enableWebkitAppRegionDClk bool
instance unsafe.Pointer
ui UITool
}
// NewApplication 创建CEF应用
......
......@@ -45,7 +45,7 @@ func (m *ICefBrowser) createBrowserDevTools(browserWindow IBrowserWindow) {
browserWindow.AsLCLBrowserWindow().BrowserWindow().createAuxTools()
browserWindow.AsLCLBrowserWindow().BrowserWindow().GetAuxTools().SetDevTools(createDevtoolsWindow(browserWindow.AsLCLBrowserWindow().BrowserWindow()))
browserWindow.AsLCLBrowserWindow().BrowserWindow().GetAuxTools().DevTools().SetCaption(fmt.Sprintf("%s - %s", devToolsName, m.MainFrame().Url()))
QueueAsyncCall(func(id int) { // show window, run is main ui thread
browserWindow.RunOnMainThread(func() { // show window, run is main ui thread
browserWindow.AsLCLBrowserWindow().BrowserWindow().GetAuxTools().DevTools().Show()
})
} else {
......
......@@ -36,7 +36,7 @@ func (m *ICefBrowser) createBrowserViewSource() {
viewSourceWindow := NewLCLBrowserWindow(nil, wp)
viewSourceWindow.SetWidth(800)
viewSourceWindow.SetHeight(600)
if common.IsDarwin() {
if common.IsDarwin() || common.IsLinux() {
viewSourceWindow.Chromium().SetOnAfterCreated(func(sender lcl.IObject, browser *ICefBrowser) {
viewSourceWindow.Chromium().LoadUrl(viewSourceUrl)
})
......
......@@ -24,7 +24,7 @@ type browserWindow struct {
mainBrowserWindow *lclBrowserWindow //LCL 主浏览器窗口
mainVFBrowserWindow *ViewsFrameworkBrowserWindow //Views Frameworks 主浏览器窗口
popupWindow IBrowserWindow //弹出的子窗口
browserEvent *BrowserEvent //浏览器全局事件
browserEvent *BrowserEvent //浏览器全局事件, 已默认实现事件
Config *browserConfig //浏览器和窗口配置
windowInfo map[int32]IBrowserWindow //窗口信息集合
}
......@@ -37,19 +37,17 @@ type BrowserEvent struct {
onDragEnter chromiumEventOnDragEnterEx //default
onDraggableRegionsChanged chromiumEventOnDraggableRegionsChangedEx //default
onLoadEnd chromiumEventOnLoadEnd //default
onAfterCreated chromiumEventOnAfterCreated //default
onAfterCreated chromiumEventOnAfterCreatedEx //default
onBeforeBrowser chromiumEventOnBeforeBrowserEx //default
onBeforeClose chromiumEventOnBeforeCloseEx //default
onClose chromiumEventOnCloseEx //default
onFrameCreated chromiumEventOnFrameCreated //default
onFrameDetached chromiumEventOnFrameDetached //default
onMainFrameChanged chromiumEventOnMainFrameChangedEx //default
onBeforeDownload chromiumEventOnBeforeDownload //default can cover
onKeyEvent chromiumEventOnKeyEventEx //default can cover
onProcessMessageReceived BrowseProcessMessageReceived //default
onTitleChange chromiumEventOnTitleChangeEx //default
onContextMenuCommand chromiumEventOnContextMenuCommand //default can cover
onBeforeContextMenu chromiumEventOnBeforeContextMenu //default can cover
onBeforeContextMenu chromiumEventOnBeforeContextMenuEx //default can cover
onBeforeResourceLoad chromiumEventOnBeforeResourceLoad //default
onRenderCompMsg chromiumEventOnCompMsg //default windows
}
......@@ -115,7 +113,9 @@ func (m *browserWindow) SetBrowserInit(fn browserWindowOnEventCallback) {
// createNextLCLPopupWindow 预创建下一个弹出的子窗口
func (m *browserWindow) createNextLCLPopupWindow() {
if m.popupWindow == nil {
m.popupWindow = NewLCLWindow(m.Config.WindowProperty, m.MainWindow().AsLCLBrowserWindow().BrowserWindow())
if mw := m.MainWindow(); mw != nil {
m.popupWindow = NewLCLWindow(m.Config.WindowProperty, mw.AsLCLBrowserWindow().BrowserWindow())
}
}
}
......@@ -158,7 +158,7 @@ func (m *browserWindow) GetBrowser(browseId int32) *ICefBrowser {
}
// SetOnAfterCreated
func (m *BrowserEvent) SetOnAfterCreated(event chromiumEventOnAfterCreated) {
func (m *BrowserEvent) SetOnAfterCreated(event chromiumEventOnAfterCreatedEx) {
if Args.IsMain() {
m.onAfterCreated = event
}
......@@ -393,7 +393,7 @@ func (m *BrowserEvent) SetOnCookieVisitorDestroyed(event chromiumEventOnCookieVi
}
// SetOnBeforeContextMenu
func (m *BrowserEvent) SetOnBeforeContextMenu(event chromiumEventOnBeforeContextMenu) {
func (m *BrowserEvent) SetOnBeforeContextMenu(event chromiumEventOnBeforeContextMenuEx) {
if Args.IsMain() {
m.onBeforeContextMenu = event
}
......@@ -420,20 +420,6 @@ func (m *BrowserEvent) SetOnFrameAttached(event chromiumEventOnFrameAttached) {
}
}
// SetOnFrameCreated
func (m *BrowserEvent) SetOnFrameCreated(event chromiumEventOnFrameCreated) {
if Args.IsMain() {
m.onFrameCreated = event
}
}
// SetOnFrameDetached
func (m *BrowserEvent) SetOnFrameDetached(event chromiumEventOnFrameDetached) {
if Args.IsMain() {
m.onFrameDetached = event
}
}
// SetOnMainFrameChanged
func (m *BrowserEvent) SetOnMainFrameChanged(event chromiumEventOnMainFrameChangedEx) {
if Args.IsMain() {
......
......@@ -20,11 +20,11 @@ import (
// 窗口拖拽JS扩展
// 在这里执行并启用JS拖拽
func dragExtensionJS(frame *ICefFrame) {
func dragExtensionJS(frame *ICefFrame, drag bool) {
// MacOS只在LCL窗口中使用自定义窗口拖拽, VF窗口默认已实现
// 在MacOS中LCL窗口没有有效的消息事件
var executeJS = `
energyExtension.drag.setEnableDrag(` + strconv.FormatBool(application.EnableWebkitAppRegion()) + `);
energyExtension.drag.setEnableDrag(` + strconv.FormatBool(drag) + `);
energyExtension.drag.setup();`
frame.ExecuteJavaScript(executeJS, "", 0)
}
......@@ -34,9 +34,6 @@ energyExtension.drag.setup();`
// 2. 通过IPC将鼠标消息发送到主进程,主进程监听到消息处理鼠标事件
// 3. macos 使用窗口坐标实现窗口拖拽
func dragExtensionHandler() {
if !application.EnableWebkitAppRegion() {
return
}
energyExtensionHandler := V8HandlerRef.New()
energyExtensionHandler.Execute(func(name string, object *ICefV8Value, arguments *TCefV8ValueArray, retVal *ResultV8Value, exception *ResultString) bool {
if name == mouseUp {
......
......@@ -12,20 +12,172 @@
package cef
import (
"github.com/energye/energy/v2/cef/internal/ipc"
ipcArgument "github.com/energye/energy/v2/cef/ipc/argument"
"strconv"
)
// 窗口拖拽JS扩展
// 在这里执行并启用JS拖拽
func dragExtensionJS(frame *ICefFrame) {
func dragExtensionJS(frame *ICefFrame, drag bool) {
// MacOS只在LCL窗口中使用自定义窗口拖拽, VF窗口默认已实现
// 在MacOS中LCL窗口没有有效的消息事件
var executeJS = `
energyExtension.drag.setEnableDrag(` + strconv.FormatBool(drag) + `);
energyExtension.drag.setup();`
frame.ExecuteJavaScript(executeJS, "", 0)
}
// 窗口拖拽JS扩展处理器
// 1. 注册JS扩展到CEF, 注册鼠标事件,通过本地函数在Go里处理鼠标事件
// 2. 通过IPC将鼠标消息发送到主进程,主进程监听到消息处理鼠标事件
// 3. linux 默认使用VF窗口组件, 所以不需要使用该实现
// 3. macos 使用窗口坐标实现窗口拖拽
func dragExtensionHandler() {
energyExtensionHandler := V8HandlerRef.New()
energyExtensionHandler.Execute(func(name string, object *ICefV8Value, arguments *TCefV8ValueArray, retVal *ResultV8Value, exception *ResultString) bool {
if name == mouseUp {
message := &ipcArgument.List{
Id: -1,
BId: ipc.RenderChan().BrowserId(),
Name: internalIPCDRAG,
Data: &drag{T: dragUp},
}
ipc.RenderChan().IPC().Send(message.Bytes())
return true
} else if name == mouseDown {
var dx, dy int32
if arguments.Size() > 0 {
point := arguments.Get(0)
v8ValX := point.getValueByKey("x")
v8ValY := point.getValueByKey("y")
dx = v8ValX.GetIntValue()
dy = v8ValY.GetIntValue()
v8ValX.Free()
v8ValY.Free()
point.Free()
}
message := &ipcArgument.List{
Id: -1,
BId: ipc.RenderChan().BrowserId(),
Name: internalIPCDRAG,
Data: &drag{T: dragDown, X: dx, Y: dy},
}
ipc.RenderChan().IPC().Send(message.Bytes())
return true
} else if name == mouseMove {
var mx, my int32
if arguments.Size() > 0 {
point := arguments.Get(0)
v8ValX := point.getValueByKey("x")
v8ValY := point.getValueByKey("y")
mx = v8ValX.GetIntValue()
my = v8ValY.GetIntValue()
v8ValX.Free()
v8ValY.Free()
point.Free()
}
message := &ipcArgument.List{
Id: -1,
BId: ipc.RenderChan().BrowserId(),
Name: internalIPCDRAG,
Data: &drag{T: dragMove, X: mx, Y: my},
}
ipc.RenderChan().IPC().Send(message.Bytes())
return true
}
return false
})
var code = `
let energyExtension;
if (!energyExtension) {
energyExtension = {
drag: {
enableDrag: false,
shouldDrag: false,
cssDragProperty: "--webkit-app-region",
cssDragValue: "drag",
defaultCursor: null
},
};
}
(function () {
energyExtension.drag.war = function (e) {
let v = window.getComputedStyle(e.target).getPropertyValue(energyExtension.drag.cssDragProperty);
if (v) {
v = v.trim();
if (v !== energyExtension.drag.cssDragValue || e.buttons !== 1) {
return false;
}
return e.detail === 1;
}
return false;
}
energyExtension.drag.mouseMove = function (e) {
if (!energyExtension.drag.enableDrag || !energyExtension.drag.shouldDrag) {
return
}
native function mouseMove();
mouseMove({x: e.screenX, y: e.screenY});
}
energyExtension.drag.mouseUp = function (e) {
if (!energyExtension.drag.enableDrag || !energyExtension.drag.shouldDrag) {
return
}
energyExtension.drag.shouldDrag = false;
//document.body.style.cursor = "default";
native function mouseUp();
mouseUp();
}
energyExtension.drag.mouseDown = function (e) {
if (!energyExtension.drag.enableDrag || ((e.offsetX > e.target.clientWidth || e.offsetY > e.target.clientHeight))) {
return
}
if (energyExtension.drag.war(e)) {
e.preventDefault();
energyExtension.drag.shouldDrag = true;
native function mouseDown();
mouseDown({x: e.screenX, y: e.screenY});
} else {
energyExtension.drag.shouldDrag = false;
}
}
energyExtension.drag.setEnableDrag = function (v) {
energyExtension.drag.enableDrag = v;
}
energyExtension.drag.setup = function () {
if (!energyExtension.drag.enableDrag) {
return;
}
window.addEventListener("mousemove", energyExtension.drag.mouseMove);
window.addEventListener("mousedown", energyExtension.drag.mouseDown);
window.addEventListener("mouseup", energyExtension.drag.mouseUp);
}
})();
`
RegisterExtension("energyExtension", code, energyExtensionHandler)
}
func (m *drag) drag() {
if m.T == dragUp {
if m.window.IsLCL() {
bw := m.window.AsLCLBrowserWindow().BrowserWindow()
bw.drag = nil
m.window = nil
}
} else if m.T == dragDown {
m.dx = m.X
m.dy = m.Y
point := m.window.Point()
m.wx = point.X
m.wy = point.Y
} else if m.T == dragMove {
m.mx = m.X
m.my = m.Y
if m.window.IsLCL() {
x := m.wx + (m.mx - m.dx)
y := m.wy + (m.my - m.dy)
m.window.SetPoint(x, y)
}
}
}
......@@ -20,10 +20,10 @@ import (
// 窗口拖拽JS扩展
// 在这里执行并启用JS拖拽
func dragExtensionJS(frame *ICefFrame) {
func dragExtensionJS(frame *ICefFrame, drag bool) {
// Windows2种方式,自定义+webkit 只在LCL窗口中使用自定义窗口拖拽, VF窗口默认已实现
var executeJS = `
energyExtension.drag.setEnableDrag(` + strconv.FormatBool(application.EnableWebkitAppRegion()) + `);
energyExtension.drag.setEnableDrag(` + strconv.FormatBool(drag) + `);
energyExtension.drag.setup();`
frame.ExecuteJavaScript(executeJS, "", 0)
}
......@@ -33,12 +33,18 @@ energyExtension.drag.setup();`
// 2. 通过IPC将鼠标消息发送到主进程,主进程监听到消息处理鼠标事件
// 3. windows 使用win.api实现窗口拖拽
func dragExtensionHandler() {
if !application.EnableWebkitAppRegion() {
return
}
energyExtensionHandler := V8HandlerRef.New()
energyExtensionHandler.Execute(func(name string, object *ICefV8Value, arguments *TCefV8ValueArray, retVal *ResultV8Value, exception *ResultString) bool {
if name == mouseUp || name == mouseDown {
if name == mouseDown {
return true
} else if name == mouseUp {
message := &ipcArgument.List{
Id: -1,
BId: ipc.RenderChan().BrowserId(),
Name: internalIPCDRAG,
Data: &drag{T: dragUp},
}
ipc.RenderChan().IPC().Send(message.Bytes())
return true
} else if name == mouseMove {
message := &ipcArgument.List{
......@@ -85,13 +91,15 @@ func dragExtensionHandler() {
mouseMove();
}
energyExtension.drag.mouseUp = function (e) {
if (!energyExtension.drag.enableDrag || !energyExtension.drag.shouldDrag) {
if (!energyExtension.drag.enableDrag) {
return
}
energyExtension.drag.shouldDrag = false;
//document.body.style.cursor = "default";
native function mouseUp();
mouseUp();
if (energyExtension.drag.war(e)) {
e.preventDefault();
native function mouseUp();
mouseUp();
}
}
energyExtension.drag.mouseDown = function (e) {
if (!energyExtension.drag.enableDrag || ((e.offsetX > e.target.clientWidth || e.offsetY > e.target.clientHeight))) {
......@@ -123,5 +131,9 @@ func dragExtensionHandler() {
}
func (m *drag) drag() {
if m.T == dragUp {
if m.window.IsLCL() {
m.window.AsLCLBrowserWindow().BrowserWindow().cwcap.canCaption = false
}
}
}
......@@ -14,12 +14,15 @@ package cef
import (
"fmt"
"github.com/energye/energy/v2/cef/internal/def"
"github.com/energye/energy/v2/cef/internal/window"
. "github.com/energye/energy/v2/common"
"github.com/energye/energy/v2/common/imports"
"github.com/energye/energy/v2/consts"
"github.com/energye/energy/v2/consts/messages"
"github.com/energye/energy/v2/logger"
"github.com/energye/energy/v2/pkgs/assetserve"
t "github.com/energye/energy/v2/types"
"github.com/energye/golcl/energy/emfs"
"github.com/energye/golcl/energy/tools"
"github.com/energye/golcl/lcl"
......@@ -28,32 +31,38 @@ import (
"github.com/energye/golcl/lcl/types"
"runtime"
"time"
"unsafe"
)
// LCLBrowserWindow 基于CEF lcl 窗口组件
//
// 该窗口使用CEF和LCL组件实现,CEF<=1.106.xx版本 在windows、MacOSX可正常使用, Linux无法输入中文, CEF>=2.107.xx版本linux强制使用 ViewsFrameworkBrowserWindow 窗口组件
type LCLBrowserWindow struct {
*lcl.TForm //window form
isFormCreate bool //是否创建完成 WindowForm
chromiumBrowser ICEFChromiumBrowser //浏览器
windowProperty *WindowProperty //窗口属性
windowId int32 //窗口ID
windowType consts.WINDOW_TYPE //窗口类型
isClosing bool //
canClose bool //
onResize TNotifyEvent //扩展事件
windowResize TNotifyEvent //扩展事件
onActivate TNotifyEvent //扩展事件
onShow TNotifyEvent //扩展事件
onClose TCloseEvent //扩展事件
onCloseQuery TCloseQueryEvent //扩展事件
onActivateAfter lcl.TNotifyEvent //扩展事件
auxTools IAuxTools //辅助工具
tray ITray //托盘
hWnd types.HWND //
cwcap *customWindowCaption //自定义窗口标题栏
drag *drag //自定义拖拽
*lcl.TForm //window form
isFormCreate bool //是否创建完成 WindowForm
chromiumBrowser ICEFChromiumBrowser //浏览器
windowProperty *WindowProperty //窗口属性
windowId int32 //窗口ID
windowType consts.WINDOW_TYPE //窗口类型
isClosing bool //
canClose bool //
onResize TNotifyEvent //扩展事件
windowResize TNotifyEvent //扩展事件
onActivate TNotifyEvent //扩展事件
onShow TNotifyEvent //扩展事件
onClose TCloseEvent //扩展事件
onCloseQuery TCloseQueryEvent //扩展事件
onActivateAfter lcl.TNotifyEvent //扩展事件
auxTools IAuxTools //辅助工具
tray ITray //托盘
hWnd types.HWND //
cwcap *customWindowCaption //自定义窗口标题栏
drag *drag //自定义拖拽
wmPaintMessage wmPaint //
wmMoveMessage wmMove //
wmSizeMessage wmSize //
wmWindowPosChangedMessage wmWindowPosChanged //
screen IScreen //屏幕
}
// NewLCLBrowserWindow 创建一个 LCL 带有 chromium 窗口
......@@ -93,39 +102,87 @@ func NewLCLWindow(windowProperty WindowProperty, owner ...lcl.IComponent) *LCLBr
// 设置属性
func (m *LCLBrowserWindow) setProperty() {
m.SetTitle(m.windowProperty.Title)
if m.windowProperty.IconFS != "" {
if emfs.IsExist(m.windowProperty.IconFS) {
_ = lcl.Application.Icon().LoadFromFSFile(m.windowProperty.IconFS)
wp := m.WindowProperty()
m.SetTitle(wp.Title)
if wp.IconFS != "" {
if emfs.IsExist(wp.IconFS) {
_ = lcl.Application.Icon().LoadFromFSFile(wp.IconFS)
}
} else if m.windowProperty.Icon != "" {
if tools.IsExist(m.windowProperty.Icon) {
lcl.Application.Icon().LoadFromFile(m.windowProperty.Icon)
} else if wp.Icon != "" {
if tools.IsExist(wp.Icon) {
lcl.Application.Icon().LoadFromFile(wp.Icon)
}
}
if m.windowProperty.EnableCenterWindow {
m.SetSize(m.windowProperty.Width, m.windowProperty.Height)
m.SetPosition(types.PoDesktopCenter)
if wp.EnableCenterWindow {
m.SetSize(wp.Width, wp.Height)
m.SetCenterWindow(true)
} else {
m.SetPosition(types.PoDesigned)
m.SetBounds(m.windowProperty.X, m.windowProperty.Y, m.windowProperty.Width, m.windowProperty.Height)
m.SetBounds(wp.X, wp.Y, wp.Width, wp.Height)
}
if m.windowProperty.AlwaysOnTop {
if wp.AlwaysOnTop {
m.SetFormStyle(types.FsSystemStayOnTop)
}
if m.windowProperty.EnableHideCaption {
if wp.EnableHideCaption {
m.HideTitle()
} else {
if !m.windowProperty.EnableMinimize {
if !wp.EnableMinimize {
m.DisableMinimize()
}
if !m.windowProperty.EnableMaximize {
if !wp.EnableMaximize {
m.DisableMaximize()
}
if !m.windowProperty.EnableResize {
if !wp.EnableResize {
m.SetBorderStyle(types.BsSingle)
}
}
if wp.EnableResize {
c := m.Constraints()
if wp.MinWidth > 0 && wp.MinHeight > 0 {
c.SetMinWidth(wp.MinWidth)
c.SetMinWidth(wp.MinHeight)
}
if wp.MaxWidth > 0 && wp.MaxHeight > 0 {
c.SetMinWidth(wp.MaxWidth)
c.SetMinWidth(wp.MaxHeight)
}
}
// 只有隐藏窗口标题时才全屏
if wp.EnableHideCaption && wp.WindowInitState == types.WsFullScreen {
m.FullScreen()
} else {
m.SetWindowState(wp.WindowInitState)
}
// 当前窗口状态
m.setCurrentProperty()
}
// FullScreen 窗口全屏
func (m *LCLBrowserWindow) FullScreen() {
if m.WindowProperty().EnableHideCaption {
m.RunOnMainThread(func() {
m.WindowProperty().current.ws = types.WsFullScreen
m.setCurrentProperty()
m.SetBoundsRect(m.Monitor().BoundsRect())
})
}
}
// ExitFullScreen 窗口退出全屏
func (m *LCLBrowserWindow) ExitFullScreen() {
wp := m.WindowProperty()
if wp.EnableHideCaption && wp.current.ws == types.WsFullScreen {
m.RunOnMainThread(func() {
wp.current.ws = types.WsNormal
m.SetWindowState(types.WsNormal)
m.SetBounds(wp.current.x, wp.current.y, wp.current.w, wp.current.h)
})
}
}
// IsFullScreen 是否全屏
func (m *LCLBrowserWindow) IsFullScreen() bool {
return m.WindowProperty().current.ws == types.WsFullScreen
}
// Handle 窗口句柄
......@@ -137,7 +194,7 @@ func (m *LCLBrowserWindow) Handle() types.HWND {
}
// RunOnMainThread
// 在主线程中运行
// 在UI主线程中运行
func (m *LCLBrowserWindow) RunOnMainThread(fn func()) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
......@@ -145,7 +202,6 @@ func (m *LCLBrowserWindow) RunOnMainThread(fn func()) {
fn()
} else {
QueueAsyncCall(func(id int) {
//lcl.ThreadSync(func() {
fn()
})
}
......@@ -172,7 +228,7 @@ func (m *LCLBrowserWindow) SetCenterWindow(value bool) {
return
}
if value {
m.SetPosition(types.PoDesktopCenter)
m.ScreenCenter()
} else {
m.SetPosition(types.PoDesigned)
}
......@@ -316,6 +372,9 @@ func (m *LCLBrowserWindow) Browser() *ICefBrowser {
// Chromium 返回 chromium
func (m *LCLBrowserWindow) Chromium() IChromium {
if m.chromiumBrowser == nil {
return nil
}
return m.chromiumBrowser.Chromium()
}
......@@ -474,6 +533,7 @@ func (m *LCLBrowserWindow) FormCreate() {
}
m.isFormCreate = true
m.SetName(fmt.Sprintf("energy_window_name_%d", time.Now().UnixNano()/1e6))
m.onFormMessages()
}
// defaultWindowEvent 默认窗口活动/关闭处理事件
......@@ -538,7 +598,7 @@ func (m *LCLBrowserWindow) Minimize() {
if m.TForm == nil {
return
}
QueueAsyncCall(func(id int) {
m.RunOnMainThread(func() {
m.SetWindowState(types.WsMinimized)
})
}
......@@ -699,6 +759,7 @@ func (m *LCLBrowserWindow) resize(sender lcl.IObject) {
if m.isClosing {
return
}
m.setCurrentProperty()
if m.windowResize != nil {
m.windowResize(sender)
}
......@@ -711,6 +772,18 @@ func (m *LCLBrowserWindow) resize(sender lcl.IObject) {
}
}
// 在窗口坐标、大小、全屏时保存当前窗口属性
func (m *LCLBrowserWindow) setCurrentProperty() {
if m.WindowProperty().current.ws == types.WsFullScreen {
return
}
boundRect := m.BoundsRect()
m.WindowProperty().current.x = boundRect.Left
m.WindowProperty().current.y = boundRect.Top
m.WindowProperty().current.w = boundRect.Width()
m.WindowProperty().current.h = boundRect.Height()
}
// activate 内部调用
func (m *LCLBrowserWindow) activate(sender lcl.IObject) {
var ret bool
......@@ -760,59 +833,52 @@ func (m *LCLBrowserWindow) registerDefaultEvent() {
}
})
m.Chromium().SetOnBeforeContextMenu(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, model *ICefMenuModel) {
var flag bool
if bwEvent.onBeforeContextMenu != nil {
bwEvent.onBeforeContextMenu(sender, browser, frame, params, model)
} else {
chromiumOnBeforeContextMenu(sender, browser, frame, params, model)
flag = bwEvent.onBeforeContextMenu(sender, browser, frame, params, model)
}
if !flag {
chromiumOnBeforeContextMenu(m, 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)
} else {
chromiumOnContextMenuCommand(sender, browser, frame, params, commandId, eventFlags, result)
}
})
m.Chromium().SetOnFrameCreated(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame) {
if bwEvent.onFrameCreated != nil {
bwEvent.onFrameCreated(sender, browser, frame)
}
})
m.Chromium().SetOnFrameDetached(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame) {
chromiumOnFrameDetached(browser, frame)
if bwEvent.onFrameDetached != nil {
bwEvent.onFrameDetached(sender, browser, frame)
if !*result {
chromiumOnContextMenuCommand(m, browser, frame, params, commandId, eventFlags, result)
}
})
m.Chromium().SetOnAfterCreated(func(sender lcl.IObject, browser *ICefBrowser) {
if chromiumOnAfterCreate(browser) {
return
}
var flag bool
if bwEvent.onAfterCreated != nil {
bwEvent.onAfterCreated(sender, browser)
flag = bwEvent.onAfterCreated(sender, browser)
}
if !flag {
chromiumOnAfterCreate(browser)
}
})
//事件可以被覆盖
m.Chromium().SetOnKeyEvent(func(sender lcl.IObject, browser *ICefBrowser, event *TCefKeyEvent, osEvent *consts.TCefEventHandle, result *bool) {
if BrowserWindow.Config.ChromiumConfig().EnableDevTools() {
if winInfo := BrowserWindow.GetWindowInfo(browser.Identifier()); winInfo != nil {
if winInfo.WindowType() == consts.WT_DEV_TOOLS || winInfo.WindowType() == consts.WT_VIEW_SOURCE {
return
if bwEvent.onKeyEvent != nil {
bwEvent.onKeyEvent(sender, browser, event, osEvent, m, result)
}
if !*result {
if m.WindowType() == consts.WT_DEV_TOOLS || m.WindowType() == consts.WT_VIEW_SOURCE {
return
}
if m.Chromium().Config().EnableDevTools() {
if event.WindowsKeyCode == consts.VkF12 && event.Kind == consts.KEYEVENT_RAW_KEYDOWN {
browser.ShowDevTools()
*result = true
} else if event.WindowsKeyCode == consts.VkF12 && event.Kind == consts.KEYEVENT_KEYUP {
*result = true
}
}
if event.WindowsKeyCode == consts.VkF12 && event.Kind == consts.KEYEVENT_RAW_KEYDOWN {
browser.ShowDevTools()
*result = true
} else if event.WindowsKeyCode == consts.VkF12 && event.Kind == consts.KEYEVENT_KEYUP {
*result = true
if KeyAccelerator.accelerator(browser, event, result) {
return
}
}
if KeyAccelerator.accelerator(browser, event, result) {
return
}
if bwEvent.onKeyEvent != nil {
bwEvent.onKeyEvent(sender, browser, event, osEvent, m, result)
}
})
m.Chromium().SetOnBeforeBrowser(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, request *ICefRequest, userGesture, isRedirect bool) bool {
if bwEvent.onBeforeBrowser != nil {
......@@ -837,7 +903,7 @@ func (m *LCLBrowserWindow) registerDefaultEvent() {
bwEvent.onLoadEnd(sender, browser, frame, httpStatusCode)
}
})
if application.EnableWebkitAppRegion() {
if m.WindowProperty().EnableWebkitAppRegion {
m.Chromium().SetOnDraggableRegionsChanged(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, regions *TCefDraggableRegions) {
if bwEvent.onDraggableRegionsChanged != nil {
bwEvent.onDraggableRegionsChanged(sender, browser, frame, regions, m)
......@@ -851,14 +917,20 @@ func (m *LCLBrowserWindow) registerDefaultEvent() {
// registerPopupEvent 注册弹出子窗口事件
func (m *LCLBrowserWindow) registerPopupEvent() {
var bwEvent = BrowserWindow.browserEvent
m.Chromium().SetOnOpenUrlFromTab(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, targetUrl string, targetDisposition consts.TCefWindowOpenDisposition, userGesture bool) bool {
if !m.Chromium().Config().EnableOpenUrlTab() {
return true
}
return false
})
m.Chromium().SetOnBeforePopup(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, beforePopupInfo *BeforePopupInfo, client *ICefClient, noJavascriptAccess *bool) bool {
if !BrowserWindow.Config.ChromiumConfig().EnableWindowPopup() {
if !m.Chromium().Config().EnableWindowPopup() {
return true
}
if next := BrowserWindow.getNextLCLPopupWindow(); next != nil {
bw := next.AsLCLBrowserWindow().BrowserWindow()
bw.SetWindowType(consts.WT_POPUP_SUB_BROWSER)
bw.ChromiumCreate(BrowserWindow.Config.ChromiumConfig(), beforePopupInfo.TargetUrl)
bw.ChromiumCreate(NewChromiumConfig(), beforePopupInfo.TargetUrl)
var result = false
if bwEvent.onBeforePopup != nil {
result = bwEvent.onBeforePopup(sender, browser, frame, beforePopupInfo, bw, noJavascriptAccess)
......@@ -868,7 +940,8 @@ func (m *LCLBrowserWindow) registerPopupEvent() {
bw.defaultChromiumEvent()
bw.registerWindowsCompMsgEvent()
bw.setProperty()
QueueAsyncCall(func(id int) { // show window, run in main thread
m.RunOnMainThread(func() {
// show window, run in main thread
if bw.WindowProperty().IsShowModel {
bw.ShowModal()
return
......@@ -885,14 +958,10 @@ func (m *LCLBrowserWindow) registerPopupEvent() {
// CloseBrowserWindow 关闭带有浏览器的窗口
func (m *LCLBrowserWindow) CloseBrowserWindow() {
if m.TForm == nil {
if m == nil || m.TForm == nil {
return
}
QueueAsyncCall(func(id int) {
if m == nil {
logger.Error("close browser WindowInfo is nil")
return
}
m.RunOnMainThread(func() {
if IsDarwin() {
//main window close
if m.WindowType() == consts.WT_MAIN_BROWSER {
......@@ -951,7 +1020,7 @@ func (m *LCLBrowserWindow) closeQuery(sender lcl.IObject, close *bool) {
} else {
*close = m.canClose
}
QueueAsyncCall(func(id int) {
m.RunOnMainThread(func() {
if !m.isClosing {
m.isClosing = true
m.Chromium().CloseBrowser(true)
......@@ -984,7 +1053,7 @@ func (m *LCLBrowserWindow) registerDefaultChromiumCloseEvent() {
*aAction = consts.CbaDelay
}
if !IsDarwin() {
QueueAsyncCall(func(id int) { //run in main thread
m.RunOnMainThread(func() { //run in main thread
m.WindowParent().Free()
logger.Debug("chromium.onClose => windowParent.Free")
})
......@@ -1007,7 +1076,6 @@ func (m *LCLBrowserWindow) registerDefaultChromiumCloseEvent() {
}
}()
if m.GetAuxTools() != nil {
m.GetAuxTools().SetViewSource(nil)
m.GetAuxTools().SetDevTools(nil)
}
......@@ -1018,7 +1086,7 @@ func (m *LCLBrowserWindow) registerDefaultChromiumCloseEvent() {
m.Close()
}
}
QueueAsyncCall(func(id int) { // main thread run
m.RunOnMainThread(func() { // main thread run
closeWindow()
})
// 最后再移除
......@@ -1027,3 +1095,114 @@ func (m *LCLBrowserWindow) registerDefaultChromiumCloseEvent() {
}
})
}
func (m *LCLBrowserWindow) Screen() IScreen {
if m.screen == nil {
m.screen = &Screen{window: m}
}
return m.screen
}
// wm message event
type messageType int32
const (
mtMove messageType = iota + 1
mtSize
mtWindowPosChanged
mtPaint
)
type wmPaint func(message *t.TPaint)
type wmMove func(message *t.TMove)
type wmSize func(message *t.TSize)
type wmWindowPosChanged func(message *t.TWindowPosChanged)
func (m *LCLBrowserWindow) onFormMessages() {
m.setOnWMPaint(func(message *t.TPaint) {
if m.Chromium() != nil {
m.Chromium().NotifyMoveOrResizeStarted()
}
if m.wmPaintMessage != nil {
m.wmPaintMessage(message)
}
})
m.setOnWMMove(func(message *t.TMove) {
m.setCurrentProperty()
if m.Chromium() != nil {
m.Chromium().NotifyMoveOrResizeStarted()
}
if m.wmMoveMessage != nil {
m.wmMoveMessage(message)
}
})
m.setOnWMSize(func(message *t.TSize) {
if m.Chromium() != nil {
m.Chromium().NotifyMoveOrResizeStarted()
}
if m.wmSizeMessage != nil {
m.wmSizeMessage(message)
}
})
m.setOnWMWindowPosChanged(func(message *t.TWindowPosChanged) {
if m.Chromium() != nil {
m.Chromium().NotifyMoveOrResizeStarted()
}
if m.wmWindowPosChangedMessage != nil {
m.wmWindowPosChangedMessage(message)
}
})
}
func (m *LCLBrowserWindow) setOnWMPaint(fn wmPaint) {
imports.Proc(def.Form_SetOnMessagesEvent).Call(m.Instance(), uintptr(mtPaint), api.MakeEventDataPtr(fn))
}
func (m *LCLBrowserWindow) setOnWMMove(fn wmMove) {
imports.Proc(def.Form_SetOnMessagesEvent).Call(m.Instance(), uintptr(mtMove), api.MakeEventDataPtr(fn))
}
func (m *LCLBrowserWindow) setOnWMSize(fn wmSize) {
imports.Proc(def.Form_SetOnMessagesEvent).Call(m.Instance(), uintptr(mtSize), api.MakeEventDataPtr(fn))
}
func (m *LCLBrowserWindow) setOnWMWindowPosChanged(fn wmWindowPosChanged) {
imports.Proc(def.Form_SetOnMessagesEvent).Call(m.Instance(), uintptr(mtWindowPosChanged), api.MakeEventDataPtr(fn))
}
func (m *LCLBrowserWindow) SetOnWMPaint(fn wmPaint) {
m.wmPaintMessage = fn
}
func (m *LCLBrowserWindow) SetOnWMMove(fn wmMove) {
m.wmMoveMessage = fn
}
func (m *LCLBrowserWindow) SetOnWMSize(fn wmSize) {
m.wmSizeMessage = fn
}
func (m *LCLBrowserWindow) SetOnWMWindowPosChanged(fn wmWindowPosChanged) {
m.wmWindowPosChangedMessage = fn
}
func init() {
lcl.RegisterExtEventCallback(func(fn interface{}, getVal func(idx int) uintptr) bool {
getPtr := func(i int) unsafe.Pointer {
return unsafe.Pointer(getVal(i))
}
switch fn.(type) {
case wmPaint:
fn.(wmPaint)((*t.TPaint)(getPtr(0)))
case wmMove:
fn.(wmMove)((*t.TMove)(getPtr(0)))
case wmSize:
fn.(wmSize)((*t.TSize)(getPtr(0)))
case wmWindowPosChanged:
fn.(wmWindowPosChanged)((*t.TWindowPosChanged)(getPtr(0)))
default:
return false
}
return true
})
}
......@@ -67,48 +67,45 @@ func (m *LCLBrowserWindow) Maximize() {
return
}
QueueAsyncCall(func(id int) {
var bs = m.BorderStyle()
var monitor = m.Monitor().WorkareaRect()
if m.windowProperty == nil {
m.windowProperty = &WindowProperty{}
}
//var bs = m.BorderStyle()
//var monitor = m.Monitor().WorkareaRect()
//这个if判断应该不会执行了,windows有自己的,linux是VF的,mac走else
if (bs == types.BsNone || bs == types.BsSingle) && !common.IsDarwin() { //不能调整窗口大,所以手动控制窗口状态
var ws = m.WindowState()
var redWindowState types.TWindowState
//默认状态0
if m.windowProperty.windowState == types.WsNormal && m.windowProperty.windowState == ws {
redWindowState = types.WsMaximized
} else {
if m.windowProperty.windowState == types.WsNormal {
redWindowState = types.WsMaximized
} else if m.windowProperty.windowState == types.WsMaximized {
redWindowState = types.WsNormal
}
}
m.windowProperty.windowState = redWindowState
if redWindowState == types.WsMaximized {
m.windowProperty.X = m.Left()
m.windowProperty.Y = m.Top()
m.windowProperty.Width = m.Width()
m.windowProperty.Height = m.Height()
m.SetBounds(monitor.Left, monitor.Top, monitor.Right-monitor.Left-1, monitor.Bottom-monitor.Top-1)
} else if redWindowState == types.WsNormal {
m.SetBounds(m.windowProperty.X, m.windowProperty.Y, m.windowProperty.Width, m.windowProperty.Height)
}
m.SetWindowState(redWindowState)
} else {
if m.WindowState() == types.WsMaximized {
m.SetWindowState(types.WsNormal)
if common.IsDarwin() { //要这样重复设置2次不然不启作用
m.SetWindowState(types.WsMaximized)
m.SetWindowState(types.WsNormal)
}
} else if m.WindowState() == types.WsNormal {
//if (bs == types.BsNone || bs == types.BsSingle) && !common.IsDarwin() { //不能调整窗口大,所以手动控制窗口状态
// var ws = m.WindowState()
// var redWindowState types.TWindowState
// //默认状态0
// if m.windowProperty.windowState == types.WsNormal && m.windowProperty.windowState == ws {
// redWindowState = types.WsMaximized
// } else {
// if m.windowProperty.windowState == types.WsNormal {
// redWindowState = types.WsMaximized
// } else if m.windowProperty.windowState == types.WsMaximized {
// redWindowState = types.WsNormal
// }
// }
// m.windowProperty.windowState = redWindowState
// if redWindowState == types.WsMaximized {
// m.windowProperty.X = m.Left()
// m.windowProperty.Y = m.Top()
// m.windowProperty.Width = m.Width()
// m.windowProperty.Height = m.Height()
// m.SetBounds(monitor.Left, monitor.Top, monitor.Right-monitor.Left-1, monitor.Bottom-monitor.Top-1)
// } else if redWindowState == types.WsNormal {
// m.SetBounds(m.windowProperty.X, m.windowProperty.Y, m.windowProperty.Width, m.windowProperty.Height)
// }
// m.SetWindowState(redWindowState)
//} else {
if m.WindowState() == types.WsMaximized {
m.SetWindowState(types.WsNormal)
if common.IsDarwin() { //要这样重复设置2次不然不启作用
m.SetWindowState(types.WsMaximized)
m.SetWindowState(types.WsNormal)
}
m.windowProperty.windowState = m.WindowState()
} else if m.WindowState() == types.WsNormal {
m.SetWindowState(types.WsMaximized)
}
//m.windowProperty.windowState = m.WindowState()
//}
})
}
......
......@@ -180,18 +180,22 @@ func (m *customWindowCaption) onCanBorder(x, y int32, rect *types.TRect) (int, b
// onNCLButtonDown NC 鼠标左键按下
func (m *customWindowCaption) onNCLButtonDown(hWND types.HWND, message *types.TMessage, lResult *types.LRESULT, aHandled *bool) {
if m.canCaption { // 标题栏
x, y := m.toPoint(message)
*lResult = messages.HTCAPTION
m.borderMD = true
*aHandled = true
//全屏时不能移动窗口
if m.bw.WindowProperty().current.ws == types.WsFullScreen {
return
}
x, y := m.toPoint(message)
m.borderMD = true
if win.ReleaseCapture() {
win.PostMessage(hWND, messages.WM_NCLBUTTONDOWN, messages.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
m.borderMD = true
if win.ReleaseCapture() {
win.PostMessage(hWND, messages.WM_SYSCOMMAND, uintptr(messages.SC_SIZE|m.borderWMSZ), rtl.MakeLParam(uint16(x), uint16(y)))
}
......@@ -216,7 +220,7 @@ func (m *customWindowCaption) isCaption(hWND et.HWND, message *types.TMessage) (
winapi.WinScreenToClient(hWND, p)
p.X -= m.bw.WindowParent().Left()
p.Y -= m.bw.WindowParent().Top()
if application.EnableWebkitAppRegion() && m.rgn != nil {
if m.bw.WindowProperty().EnableWebkitAppRegion && m.rgn != nil {
m.canCaption = winapi.WinPtInRegion(m.rgn, p.X, p.Y)
} else {
m.canCaption = false
......@@ -229,12 +233,11 @@ func (m *LCLBrowserWindow) doOnRenderCompMsg(message *types.TMessage, lResult *t
switch message.Msg {
case messages.WM_NCLBUTTONDBLCLK: // 163 NC left dclick
//标题栏拖拽区域 双击最大化和还原
if m.cwcap.canCaption && application.EnableWebkitAppRegionDClk() {
if m.cwcap.canCaption && m.WindowProperty().EnableWebkitAppRegionDClk {
*lResult = messages.HTCAPTION
*aHandled = true
if win.ReleaseCapture() {
m.windowProperty.windowState = m.WindowState()
if m.windowProperty.windowState == types.WsNormal {
if m.WindowState() == types.WsNormal {
win.PostMessage(m.Handle(), messages.WM_SYSCOMMAND, messages.SC_MAXIMIZE, 0)
} else {
win.PostMessage(m.Handle(), messages.WM_SYSCOMMAND, messages.SC_RESTORE, 0)
......@@ -264,6 +267,10 @@ func (m *LCLBrowserWindow) doOnRenderCompMsg(message *types.TMessage, lResult *t
*lResult = messages.HTCAPTION
*aHandled = true
} else if m.WindowProperty().EnableHideCaption && m.WindowProperty().EnableResize && m.WindowState() == types.WsNormal { //1.窗口隐藏标题栏 2.启用了调整窗口大小 3.非最大化、最小化、全屏状态
//全屏时不能调整窗口大小
if m.WindowProperty().current.ws == types.WsFullScreen {
return
}
rect := m.BoundsRect()
if result, handled := m.cwcap.onCanBorder(x, y, &rect); handled {
*lResult = types.LRESULT(result)
......@@ -277,7 +284,7 @@ func (m *LCLBrowserWindow) doOnRenderCompMsg(message *types.TMessage, lResult *t
// 每一次拖拽区域改变都需要重新设置
func (m *LCLBrowserWindow) setDraggableRegions() {
//在主线程中运行
QueueAsyncCall(func(id int) {
m.RunOnMainThread(func() {
if m.cwcap.rgn == nil {
//第一次时创建RGN
m.cwcap.rgn = winapi.WinCreateRectRgn(0, 0, 0, 0)
......@@ -310,7 +317,7 @@ func (m *LCLBrowserWindow) registerWindowsCompMsgEvent() {
m.doOnRenderCompMsg(message, lResult, aHandled)
}
})
if application.EnableWebkitAppRegion() && application.EnableWebkitAppRegionDClk() {
if m.WindowProperty().EnableWebkitAppRegion && m.WindowProperty().EnableWebkitAppRegionDClk {
m.windowResize = func(sender lcl.IObject) bool {
if m.WindowState() == types.WsMaximized && (m.WindowProperty().EnableHideCaption || m.BorderStyle() == types.BsNone || m.BorderStyle() == types.BsSingle) {
var monitor = m.Monitor().WorkareaRect()
......@@ -335,10 +342,9 @@ func (m *LCLBrowserWindow) Maximize() {
if m.TForm == nil {
return
}
QueueAsyncCall(func(id int) {
m.RunOnMainThread(func() {
if win.ReleaseCapture() {
m.windowProperty.windowState = m.WindowState()
if m.windowProperty.windowState == types.WsNormal {
if m.WindowState() == types.WsNormal {
win.PostMessage(m.Handle(), messages.WM_SYSCOMMAND, messages.SC_MAXIMIZE, 0)
} else {
win.SendMessage(m.Handle(), messages.WM_SYSCOMMAND, messages.SC_RESTORE, 0)
......@@ -364,7 +370,18 @@ func (m *LCLBrowserWindow) Maximize() {
func (m *LCLBrowserWindow) doDrag() {
// Windows Drag Window
if win.ReleaseCapture() {
win.PostMessage(m.Handle(), messages.WM_NCLBUTTONDOWN, messages.HTCAPTION, 0)
// m.drag != nil 时,这里处理的是 up 事件, 给标题栏标记为false
if m.drag != nil {
m.drag.drag()
} else {
// 全屏时不能拖拽窗口
if m.WindowProperty().current.ws == types.WsFullScreen {
return
}
// 此时是 down 事件, 拖拽窗口
if win.ReleaseCapture() {
win.PostMessage(m.Handle(), messages.WM_NCLBUTTONDOWN, messages.HTCAPTION, 0)
m.cwcap.canCaption = true
}
}
}
......@@ -46,20 +46,16 @@ type ViewsFrameworkBrowserWindow struct {
doOnWindowCreated WindowComponentOnWindowCreated //窗口创建
doOnGetInitialBounds WindowComponentOnGetInitialBounds //窗口初始bounds
regions *TCefDraggableRegions //窗口内html拖拽区域
context *ICefRequestContext
extraInfo *ICefDictionaryValue
context *ICefRequestContext //
extraInfo *ICefDictionaryValue //
screen IScreen //屏幕
}
// NewViewsFrameworkBrowserWindow 创建 ViewsFrameworkBrowserWindow 窗口
func NewViewsFrameworkBrowserWindow(config *TCefChromiumConfig, windowProperty WindowProperty, owner ...lcl.IComponent) *ViewsFrameworkBrowserWindow {
if config == nil {
config = NewChromiumConfig()
config.SetEnableViewSource(false)
config.SetEnableDevTools(false)
config.SetEnableMenu(false)
config.SetEnableWindowPopup(false)
}
var component lcl.IComponent
if len(owner) > 0 {
component = lcl.NewComponent(owner[0])
......@@ -109,52 +105,88 @@ func NewViewsFrameworkBrowserWindow(config *TCefChromiumConfig, windowProperty W
// ViewsFrameworkBrowserWindow 主窗口初始化
func (m *browserWindow) appContextInitialized(app *TCEFApplication) {
// 仅主进程初始化主窗口,
// 子进程也不会初始, 判断一下省着多调用函数了
if !process.Args.IsMain() {
return
}
// VF 主窗口在 application 上下文初始化时创建
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) {
// main window
vfMainWindow := NewViewsFrameworkBrowserWindow(m.Config.ChromiumConfig(), m.Config.WindowProperty)
// 主窗口关闭流程 before close
// OnCanClose如果阻止关闭,该函数不会执行
vfMainWindow.Chromium().SetOnBeforeClose(func(sender lcl.IObject, browser *ICefBrowser) {
chromiumOnBeforeClose(browser)
if vFrameBrowserWindow.tray != nil {
vFrameBrowserWindow.tray.close()
if vfMainWindow.tray != nil {
vfMainWindow.tray.close()
}
app.QuitMessageLoop()
})
// 重置窗口属性, 注册默认实现事件
vFrameBrowserWindow.ResetWindowPropertyForEvent()
vFrameBrowserWindow.registerPopupEvent(true)
vFrameBrowserWindow.registerDefaultEvent()
vFrameBrowserWindow.windowComponent.SetOnCanClose(func(sender lcl.IObject, window *ICefWindow, aResult *bool) {
*aResult = vFrameBrowserWindow.Chromium().TryCloseBrowser()
vfMainWindow.ResetWindowPropertyForEvent()
vfMainWindow.registerPopupEvent(true)
vfMainWindow.registerDefaultEvent()
vfMainWindow.windowComponent.SetOnCanClose(func(sender lcl.IObject, window *ICefWindow, aResult *bool) {
*aResult = vfMainWindow.Chromium().TryCloseBrowser()
})
BrowserWindow.mainVFBrowserWindow = vFrameBrowserWindow
// 设置到 MainBrowser
BrowserWindow.mainVFBrowserWindow = vfMainWindow
if m.Config.browserWindowOnEventCallback != nil {
BrowserWindow.browserEvent.chromium = vFrameBrowserWindow.chromium
m.Config.browserWindowOnEventCallback(BrowserWindow.browserEvent, vFrameBrowserWindow)
BrowserWindow.browserEvent.chromium = vfMainWindow.chromium
m.Config.browserWindowOnEventCallback(BrowserWindow.browserEvent, vfMainWindow)
}
ipc.SetProcessMessage(vFrameBrowserWindow.Chromium().(*TCEFChromium))
vFrameBrowserWindow.CreateTopLevelWindow()
ipc.SetProcessMessage(vfMainWindow.Chromium().(*TCEFChromium))
vfMainWindow.CreateTopLevelWindow()
//创建完窗口之后设置窗口属性
vfMainWindow.createAfterWindowPropertyForEvent()
})
}
func (m *ViewsFrameworkBrowserWindow) createAfterWindowPropertyForEvent() {
wp := m.WindowProperty()
if wp.EnableResize {
// VF MinimumSize & MaximumSize 在事件中设置
// 如果动态设置,需要自己实现该回调函数
if wp.MinWidth > 0 && wp.MinHeight > 0 {
m.windowComponent.SetOnGetMinimumSize(func(view *ICefView, result *TCefSize) {
result.Width = int32(wp.MinWidth)
result.Height = int32(wp.MinHeight)
})
}
if wp.MaxWidth > 0 && wp.MaxHeight > 0 {
m.windowComponent.SetOnGetMaximumSize(func(view *ICefView, result *TCefSize) {
result.Width = int32(wp.MaxWidth)
result.Height = int32(wp.MaxHeight)
})
}
}
}
// registerPopupEvent 注册弹出子窗口事件
func (m *ViewsFrameworkBrowserWindow) registerPopupEvent(isMain bool) {
var bwEvent = BrowserWindow.browserEvent
if !isMain {
// 子窗口关闭流程
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 !BrowserWindow.Config.ChromiumConfig().EnableWindowPopup() {
m.Chromium().SetOnOpenUrlFromTab(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, targetUrl string, targetDisposition consts.TCefWindowOpenDisposition, userGesture bool) bool {
if !m.Chromium().Config().EnableOpenUrlTab() {
return true
}
return false
})
m.Chromium().SetOnBeforePopup(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, beforePopupInfo *BeforePopupInfo, client *ICefClient, noJavascriptAccess *bool) bool {
if !m.Chromium().Config().EnableWindowPopup() {
return true
}
wp := BrowserWindow.Config.WindowProperty
wp := *m.windowProperty //clone
wp.Url = beforePopupInfo.TargetUrl
wp.WindowType = consts.WT_POPUP_SUB_BROWSER
var vFrameBrowserWindow = NewViewsFrameworkBrowserWindow(BrowserWindow.Config.ChromiumConfig(), wp, BrowserWindow.MainWindow().AsViewsFrameworkBrowserWindow().Component())
var vFrameBrowserWindow = NewViewsFrameworkBrowserWindow(NewChromiumConfig(), wp, BrowserWindow.MainWindow().AsViewsFrameworkBrowserWindow().Component())
var result = false
if bwEvent.onBeforePopup != nil {
result = bwEvent.onBeforePopup(sender, browser, frame, beforePopupInfo, vFrameBrowserWindow, noJavascriptAccess)
......@@ -173,6 +205,9 @@ func (m *ViewsFrameworkBrowserWindow) registerPopupEvent(isMain bool) {
// ResetWindowPropertyForEvent 重置窗口属性-通过事件函数
func (m *ViewsFrameworkBrowserWindow) ResetWindowPropertyForEvent() {
wp := m.WindowProperty()
m.windowComponent.SetOnGetInitialShowState(func(sender lcl.IObject, window *ICefWindow, aResult *consts.TCefShowState) {
*aResult = consts.TCefShowState(wp.WindowInitState + 1) // CEF 要 + 1
})
m.windowComponent.SetOnGetInitialBounds(func(sender lcl.IObject, window *ICefWindow, aResult *TCefRect) {
if wp.EnableCenterWindow {
m.windowComponent.CenterWindow(NewCefSize(wp.Width, wp.Height))
......@@ -234,48 +269,40 @@ func (m *ViewsFrameworkBrowserWindow) registerDefaultEvent() {
}
})
m.chromium.SetOnBeforeContextMenu(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, model *ICefMenuModel) {
var flag bool
if bwEvent.onBeforeContextMenu != nil {
bwEvent.onBeforeContextMenu(sender, browser, frame, params, model)
} else {
chromiumOnBeforeContextMenu(sender, browser, frame, params, model)
}
if !flag {
chromiumOnBeforeContextMenu(m, 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)
} else {
chromiumOnContextMenuCommand(sender, browser, frame, params, commandId, eventFlags, result)
}
})
m.chromium.SetOnFrameCreated(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame) {
if bwEvent.onFrameCreated != nil {
bwEvent.onFrameCreated(sender, browser, frame)
}
})
m.chromium.SetOnFrameDetached(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame) {
chromiumOnFrameDetached(browser, frame)
if bwEvent.onFrameDetached != nil {
bwEvent.onFrameDetached(sender, browser, frame)
if !*result {
chromiumOnContextMenuCommand(m, browser, frame, params, commandId, eventFlags, result)
}
})
m.chromium.SetOnAfterCreated(func(sender lcl.IObject, browser *ICefBrowser) {
if chromiumOnAfterCreate(browser) {
return
}
var flag bool
if bwEvent.onAfterCreated != nil {
bwEvent.onAfterCreated(sender, browser)
flag = bwEvent.onAfterCreated(sender, browser)
}
if !flag {
chromiumOnAfterCreate(browser)
}
})
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, osEvent, m, result)
} else {
if BrowserWindow.Config.ChromiumConfig().EnableDevTools() {
if winInfo := BrowserWindow.GetWindowInfo(browser.Identifier()); winInfo != nil {
if winInfo.WindowType() == consts.WT_DEV_TOOLS || winInfo.WindowType() == consts.WT_VIEW_SOURCE {
return
}
}
}
if !*result {
if m.WindowType() == consts.WT_DEV_TOOLS || m.WindowType() == consts.WT_VIEW_SOURCE {
return
}
if m.Chromium().Config().EnableDevTools() {
if event.WindowsKeyCode == consts.VkF12 && event.Kind == consts.KEYEVENT_RAW_KEYDOWN {
browser.ShowDevTools()
*result = true
......@@ -310,7 +337,7 @@ func (m *ViewsFrameworkBrowserWindow) registerDefaultEvent() {
bwEvent.onLoadEnd(sender, browser, frame, httpStatusCode)
}
})
if application.EnableWebkitAppRegion() {
if m.WindowProperty().EnableWebkitAppRegion {
m.chromium.SetOnDraggableRegionsChanged(func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, regions *TCefDraggableRegions) {
if bwEvent.onDraggableRegionsChanged != nil {
bwEvent.onDraggableRegionsChanged(sender, browser, frame, regions, m)
......@@ -499,14 +526,25 @@ func (m *ViewsFrameworkBrowserWindow) WindowState() types.TWindowState {
// Maximize 窗口最大化/还原
func (m *ViewsFrameworkBrowserWindow) Maximize() {
m.windowProperty.windowState = m.WindowState()
if m.windowProperty.windowState == types.WsNormal {
if m.WindowState() == types.WsNormal {
m.WindowComponent().Maximize()
} else {
m.Restore()
}
}
func (m *ViewsFrameworkBrowserWindow) FullScreen() {
m.WindowComponent().SetFullscreen(true)
}
func (m *ViewsFrameworkBrowserWindow) ExitFullScreen() {
m.WindowComponent().SetFullscreen(false)
}
func (m *ViewsFrameworkBrowserWindow) IsFullScreen() bool {
return m.WindowComponent().IsFullscreen()
}
// Minimize 窗口最小化
func (m *ViewsFrameworkBrowserWindow) Minimize() {
m.WindowComponent().Minimize()
......@@ -601,6 +639,13 @@ func (m *ViewsFrameworkBrowserWindow) BrowserViewComponent() *TCEFBrowserViewCom
return m.browserViewComponent
}
func (m *ViewsFrameworkBrowserWindow) Screen() IScreen {
if m.screen == nil && m.BrowserViewComponent() != nil {
m.screen = &Screen{window: m}
}
return m.screen
}
// RunOnMainThread
// 在主线程中运行
func (m *ViewsFrameworkBrowserWindow) RunOnMainThread(fn func()) {
......
......@@ -25,36 +25,47 @@ type auxTools struct {
viewSourceWindow IBrowserWindow //viewSource
}
// 窗口当前属性
type windowCurrentProperty struct {
ws types.TWindowState
x, y, w, h int32
}
// WindowProperty
// 窗口属性配置器
//
// 部分属性配置并不支持所有平台
// 提供部分窗口属性配置,初始化时生效
// 如需更多属性配置或自定义窗口行为请在`SetBrowserInit`回调函数中使用
type WindowProperty struct {
IsShowModel bool //是否以模态窗口显示
windowState types.TWindowState //窗口 状态
WindowType consts.WINDOW_TYPE //窗口 类型 WINDOW_TYPE default: WT_MAIN_BROWSER
Title string //窗口 标题
Url string //默认打开URL
Icon string //窗口图标 加载本地图标 local > /app/resources/icon.ico, linux使用png
IconFS string //窗口图标 加载emfs内置图标 emfs > resources/icon.ico, linux使用png
EnableHideCaption bool //窗口 是否隐藏标题栏, VF窗口组件Linux下不能动态控制
EnableMinimize bool //窗口 是否启用最小化 default: true
EnableMaximize bool //窗口 是否启用最大化 default: true
EnableResize bool //窗口 是否允许调整大小 default: true
EnableClose bool //窗口 关闭时是否关闭窗口 default: true
EnableCenterWindow bool //窗口 居中显示 default: true
EnableDragFile bool //窗口 是否允许向窗口内拖拽文件
AlwaysOnTop bool //窗口 窗口置顶
X int32 //窗口 EnableCenterWindow=false X坐标 default: 100
Y int32 //窗口 EnableCenterWindow=false Y坐标 default: 100
Width int32 //窗口 宽 default: 1024
Height int32 //窗口 高 default: 768
IsShowModel bool // 是否以模态窗口显示
WindowInitState types.TWindowState // 窗口 初始状态: 最小化、最大化、全屏, 全屏时隐藏标题栏生效
WindowType consts.WINDOW_TYPE // 窗口 类型 WINDOW_TYPE default: WT_MAIN_BROWSER
Title string // 窗口 标题
Url string // 默认打开URL
Icon string // 窗口图标 加载本地图标 local > /app/resources/icon.ico, VF窗口linux使用png
IconFS string // 窗口图标 加载emfs内置图标 emfs > resources/icon.ico, VF窗口linux使用png
EnableWebkitAppRegion bool //
EnableWebkitAppRegionDClk bool //
EnableHideCaption bool // 窗口 是否隐藏标题栏, VF窗口组件Linux下不能动态控制
EnableMinimize bool // 窗口 是否启用最小化 default: true
EnableMaximize bool // 窗口 是否启用最大化 default: true
EnableResize bool // 窗口 是否允许调整大小 default: true
EnableClose bool // 窗口 关闭时是否关闭窗口 default: true
EnableCenterWindow bool // 窗口 居中显示 default: true
EnableDragFile bool // 窗口 是否允许向窗口内拖拽文件
AlwaysOnTop bool // 窗口 窗口置顶
X int32 // 窗口 EnableCenterWindow=false X坐标 default: 100
Y int32 // 窗口 EnableCenterWindow=false Y坐标 default: 100
Width int32 // 窗口 宽 default: 1024
Height int32 // 窗口 高 default: 768
MinWidth types.TConstraintSize // 窗口 最小宽, EnableResize = true 与 MinHeight > 0 生效
MinHeight types.TConstraintSize // 窗口 最小高, EnableResize = true 与 MinWidth > 0 生效
MaxWidth types.TConstraintSize // 窗口 最大宽, EnableResize = true 与 MaxHeight > 0 生效
MaxHeight types.TConstraintSize // 窗口 最大高, EnableResize = true 与 MaxWidth > 0 生效
current windowCurrentProperty // 窗口 当前属性
}
// IBrowserWindow
// 浏览器窗口基础接口
//
// 定义了常用函数
// 浏览器窗口基础接口
// 定义了常用函数, 更多窗口功能或属性在SetBrowserInit函数中使用
type IBrowserWindow interface {
Id() int32 //窗口ID
Handle() types.HWND //窗口句柄
......@@ -64,6 +75,9 @@ type IBrowserWindow interface {
Maximize() //窗口最大化
Minimize() //窗口最小化
Restore() //窗口还原
FullScreen() //全屏模式, 仅隐藏标题栏时有效
ExitFullScreen() //退出全屏模式
IsFullScreen() bool //是否全屏模式
Close() //关闭窗口 非browser窗口使用
CloseBrowserWindow() //关闭浏览器窗口 带有browser窗口使用
WindowType() consts.WINDOW_TYPE //窗口类型
......@@ -101,7 +115,8 @@ type IBrowserWindow interface {
NewCefTray(width, height int32, url string) ITray //仅支持windows托盘LCL+[CEF|VF](使用web端技术自定义实现,如使用LCL窗口组件该托盘实现是LCL+CEF,如使用VF窗口组件该托盘实现是LCL+VF)
NewSysTray() ITray //systray系统原生
SetCreateBrowserExtraInfo(windowName string, context *ICefRequestContext, extraInfo *ICefDictionaryValue) //设置 Chromium 创建浏览器时设置的扩展信息
RunOnMainThread(fn func()) //在主线程中运行
RunOnMainThread(fn func()) //在UI主线程中运行
Screen() IScreen //返回屏幕信息
}
// ILCLBrowserWindow
......@@ -141,26 +156,26 @@ type IViewsFrameworkBrowserWindow interface {
type IAuxTools interface {
SetDevTools(devToolsWindow *devToolsWindow)
SetViewSource(viewSourceWindow IBrowserWindow)
DevTools() *devToolsWindow
ViewSource() IBrowserWindow
}
// NewWindowProperty
// 创建一个属性配置器,带有窗口默认属性值
func NewWindowProperty() WindowProperty {
return WindowProperty{
Title: "ENERGY",
Url: "about:blank",
EnableMinimize: true,
EnableMaximize: true,
EnableResize: true,
EnableClose: true,
EnableCenterWindow: true,
X: 100,
Y: 100,
Width: 1024,
Height: 768,
Title: "ENERGY",
Url: "about:blank",
EnableMinimize: true,
EnableMaximize: true,
EnableResize: true,
EnableClose: true,
EnableCenterWindow: true,
EnableWebkitAppRegion: true,
EnableWebkitAppRegionDClk: true,
X: 100,
Y: 100,
Width: 1024,
Height: 768,
}
}
......@@ -168,14 +183,6 @@ func (m *auxTools) SetDevTools(devToolsWindow *devToolsWindow) {
m.devToolsWindow = devToolsWindow
}
func (m *auxTools) SetViewSource(viewSourceWindow IBrowserWindow) {
m.viewSourceWindow = viewSourceWindow
}
func (m *auxTools) DevTools() *devToolsWindow {
return m.devToolsWindow
}
func (m *auxTools) ViewSource() IBrowserWindow {
return m.viewSourceWindow
}
......@@ -56,12 +56,18 @@ func chromiumOnBeforeBrowser(browser *ICefBrowser, frame *ICefFrame) {
return
}
window.CurrentBrowseWindowCache = nil
// 辅助工具不具有浏览器窗口特性
if bw.WindowType() == consts.WT_DEV_TOOLS || bw.WindowType() == consts.WT_VIEW_SOURCE ||
bw.WindowProperty().WindowType == consts.WT_DEV_TOOLS || bw.WindowProperty().WindowType == consts.WT_VIEW_SOURCE {
return
}
BrowserWindow.putWindowInfo(browser.BrowserId(), bw)
// 只LCL窗口使用自定义的窗口拖拽
if bw.IsLCL() {
dragExtensionJS(frame, bw.WindowProperty().EnableWebkitAppRegion) // drag extension
}
}
// 当前应用是LCL窗口预先创建下一个window
if !application.IsMessageLoop() {
QueueAsyncCall(func(id int) {
// lcl
......@@ -75,10 +81,6 @@ func chromiumOnBeforeClose(browser *ICefBrowser) {
BrowserWindow.removeWindowInfo(browser.Identifier())
}
// chromiumOnFrameDetached
func chromiumOnFrameDetached(browser *ICefBrowser, frame *ICefFrame) {
}
var (
refreshId, forcedRefreshId consts.MenuId
devToolsId, viewSourceId, closeBrowserId consts.MenuId
......@@ -88,16 +90,14 @@ var (
)
// chromiumOnBeforeContextMenu 右键菜单 - 默认实现
func chromiumOnBeforeContextMenu(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, model *ICefMenuModel) {
if !BrowserWindow.Config.ChromiumConfig().EnableMenu() {
func chromiumOnBeforeContextMenu(window IBrowserWindow, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, model *ICefMenuModel) {
if !window.Chromium().Config().EnableMenu() {
model.Clear()
return
}
if winInfo := BrowserWindow.GetWindowInfo(browser.Identifier()); winInfo != nil {
//开发者工具和显示源代码不展示自定义默认菜单
if winInfo.WindowType() == consts.WT_DEV_TOOLS || winInfo.WindowType() == consts.WT_VIEW_SOURCE {
return
}
//开发者工具和显示源代码不展示自定义默认菜单
if window.WindowType() == consts.WT_DEV_TOOLS || window.WindowType() == consts.WT_VIEW_SOURCE {
return
}
undoVisible, undoEnabled := model.IsVisible(consts.MENU_ID_UNDO), model.IsEnabled(consts.MENU_ID_UNDO)
redoVisible, redoEnabled := model.IsVisible(consts.MENU_ID_REDO), model.IsEnabled(consts.MENU_ID_REDO)
......@@ -255,7 +255,7 @@ func chromiumOnBeforeContextMenu(sender lcl.IObject, browser *ICefBrowser, frame
},
})
model.AddSeparator()
if BrowserWindow.Config.ChromiumConfig().EnableViewSource() {
if window.Chromium().Config().EnableViewSource() {
viewSourceId = model.CefMis.NextCommandId()
model.AddMenuItem(&MenuItem{
CommandId: viewSourceId,
......@@ -266,7 +266,7 @@ func chromiumOnBeforeContextMenu(sender lcl.IObject, browser *ICefBrowser, frame
},
})
}
if BrowserWindow.Config.ChromiumConfig().EnableDevTools() {
if window.Chromium().Config().EnableDevTools() {
devToolsId = model.CefMis.NextCommandId()
model.AddItem(devToolsId, i18n.Resource("devTools"))
}
......@@ -283,7 +283,7 @@ func chromiumOnBeforeContextMenu(sender lcl.IObject, browser *ICefBrowser, frame
}
// chromiumOnContextMenuCommand 右键菜单 - 默认实现
func chromiumOnContextMenuCommand(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, commandId consts.MenuId, eventFlags uint32, result *bool) {
func chromiumOnContextMenuCommand(window IBrowserWindow, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, commandId consts.MenuId, eventFlags uint32, result *bool) {
browserId := browser.Identifier()
defer func() {
if err := recover(); err != nil {
......@@ -305,11 +305,11 @@ func chromiumOnContextMenuCommand(sender lcl.IObject, browser *ICefBrowser, fram
} else if commandId == forcedRefreshId {
browser.ReloadIgnoreCache()
} else if commandId == viewSourceId {
if BrowserWindow.Config.ChromiumConfig().EnableViewSource() {
if window.Chromium().Config().EnableViewSource() {
browser.ViewSource()
}
} else if commandId == devToolsId {
if BrowserWindow.Config.ChromiumConfig().EnableDevTools() {
if window.Chromium().Config().EnableDevTools() {
browser.ShowDevTools()
}
} else if commandId == aUrlId {
......
......@@ -122,6 +122,7 @@ type chromiumEventOnTitleChangeEx func(sender lcl.IObject, browser *ICefBrowser,
type chromiumEventOnRenderProcessTerminated func(sender lcl.IObject, browser *ICefBrowser, status consts.TCefTerminationStatus)
type chromiumEventOnCompMsg func(sender lcl.IObject, message *types.TMessage, lResult *types.LRESULT, aHandled *bool)
type chromiumEventOnAfterCreated func(sender lcl.IObject, browser *ICefBrowser)
type chromiumEventOnAfterCreatedEx func(sender lcl.IObject, browser *ICefBrowser) bool
type chromiumEventOnBeforeClose func(sender lcl.IObject, browser *ICefBrowser)
type chromiumEventOnBeforeCloseEx func(sender lcl.IObject, browser *ICefBrowser, window IBrowserWindow) bool
type chromiumEventOnClose func(sender lcl.IObject, browser *ICefBrowser, aAction *consts.TCefCloseBrowserAction)
......@@ -138,6 +139,7 @@ type chromiumEventOnCookiesFlushed func(sender lcl.IObject)
type chromiumEventOnCookiesVisited func(sender lcl.IObject, cookie *ICefCookie)
type chromiumEventOnCookieVisitorDestroyed func(sender lcl.IObject, ID int32)
type chromiumEventOnBeforeContextMenu func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, model *ICefMenuModel)
type chromiumEventOnBeforeContextMenuEx func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, model *ICefMenuModel) bool
type chromiumEventOnContextMenuCommand func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, params *ICefContextMenuParams, commandId consts.MenuId, eventFlags uint32, result *bool)
type chromiumEventOnContextMenuDismissed func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame)
type chromiumEventOnFullScreenModeChange func(sender lcl.IObject, browser *ICefBrowser, fullscreen bool)
......@@ -157,7 +159,7 @@ type chromiumEventOnMainFrameChanged func(sender lcl.IObject, browser *ICefBrows
type chromiumEventOnMainFrameChangedEx func(sender lcl.IObject, browser *ICefBrowser, oldFrame *ICefFrame, newFrame *ICefFrame, window IBrowserWindow)
type chromiumEventOnBeforePopup func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, beforePopupInfo *BeforePopupInfo, client *ICefClient, noJavascriptAccess *bool) bool
type chromiumEventOnBeforePopupEx func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, beforePopupInfo *BeforePopupInfo, popupWindow IBrowserWindow, noJavascriptAccess *bool) bool
type chromiumEventOnOpenUrlFromTab func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, targetUrl string, targetDisposition consts.TCefWindowOpenDisposition, userGesture bool, result *bool)
type chromiumEventOnOpenUrlFromTab func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, targetUrl string, targetDisposition consts.TCefWindowOpenDisposition, userGesture bool) bool
type chromiumEventOnDragEnter func(sender lcl.IObject, browser *ICefBrowser, dragData *ICefDragData, mask consts.TCefDragOperations, result *bool)
type chromiumEventOnDragEnterEx func(sender lcl.IObject, browser *ICefBrowser, dragData *ICefDragData, mask consts.TCefDragOperations, window IBrowserWindow, result *bool)
type chromiumEventOnDraggableRegionsChanged func(sender lcl.IObject, browser *ICefBrowser, frame *ICefFrame, regions *TCefDraggableRegions)
......
......@@ -868,9 +868,14 @@ func init() {
//callback
*result = fn.(chromiumEventOnBeforePopup)(lcl.AsObject(sender), browse, frame, beforePopupInfo, client, noJavascriptAccess)
case chromiumEventOnOpenUrlFromTab:
//no impl
sender := getPtr(0)
browse := &ICefBrowser{instance: getPtr(1)}
frame := &ICefFrame{instance: getPtr(2)}
targetUrl := api.GoStr(getVal(3))
targetDisposition := consts.TCefWindowOpenDisposition(getVal(4))
userGesture := api.GoBool(getVal(5))
result := (*bool)(getPtr(6))
*result = true
*result = fn.(chromiumEventOnOpenUrlFromTab)(lcl.AsObject(sender), browse, frame, targetUrl, targetDisposition, userGesture)
case chromiumEventOnDragEnter:
sender := getPtr(0)
browse := &ICefBrowser{instance: getPtr(1)}
......
......@@ -23,6 +23,8 @@ package def
const (
//null nil
null_nil = iota
// TForm
Form_SetOnMessagesEvent
// CEF
LibVersion
LibBuildVersion
......@@ -232,9 +234,6 @@ const (
CEFApplication_QueueAsyncCall
SetCEFWindowBindCallbackFunc // no impl
SetCEFIPCCallbackFunc // no impl
// GoForm
CEF_AddGoForm // no impl
CEF_RemoveGoForm // no impl
// ICefCallback
CEFCallback_Cont
CEFCallback_Cancel
......@@ -1207,6 +1206,16 @@ const (
CEFBrowserViewComponent_SetOnPopupBrowserViewCreated
CEFBrowserViewComponent_SetOnGetChromeToolbarType
// ICefDisplay
CEFDisplayRef_Primary
CEFDisplayRef_NearestPoint
CEFDisplayRef_MatchingBounds
CEFDisplayRef_GetCount
CEFDisplayRef_GetAlls
CEFDisplayRef_Get
CEFDisplayRef_ScreenPointToPixels
CEFDisplayRef_ScreenPointFromPixels
CEFDisplayRef_ScreenRectToPixels
CEFDisplayRef_ScreenRectFromPixels
CEFDisplay_ID
CEFDisplay_DeviceScaleFactor
CEFDisplay_Rotation
......
......@@ -23,6 +23,8 @@ func init() {
var energyImportDefs = []*dllimports.ImportTable{
//null nil
dllimports.NewEnergyImport("", 0),
// TForm
dllimports.NewEnergyImport("Form_SetOnMessagesEvent", 0),
//CEF
dllimports.NewEnergyImport("LibVersion", 0),
dllimports.NewEnergyImport("LibBuildVersion", 0),
......@@ -232,9 +234,6 @@ func init() {
dllimports.NewEnergyImport("CEFApplication_QueueAsyncCall", 0),
dllimports.NewEnergyImport("SetCEFWindowBindCallbackFunc", 0),
dllimports.NewEnergyImport("SetCEFIPCCallbackFunc", 0),
//GoForm
dllimports.NewEnergyImport("CEF_AddGoForm", 0),
dllimports.NewEnergyImport("CEF_RemoveGoForm", 0),
//ICefCallback
dllimports.NewEnergyImport("cefCallback_Cont", 0),
dllimports.NewEnergyImport("cefCallback_Cancel", 0),
......@@ -1207,6 +1206,16 @@ func init() {
dllimports.NewEnergyImport("CEFBrowserViewComponent_SetOnPopupBrowserViewCreated", 0),
dllimports.NewEnergyImport("CEFBrowserViewComponent_SetOnGetChromeToolbarType", 0),
//ICefDisplay
dllimports.NewEnergyImport("CEFDisplayRef_Primary", 0),
dllimports.NewEnergyImport("CEFDisplayRef_NearestPoint", 0),
dllimports.NewEnergyImport("CEFDisplayRef_MatchingBounds", 0),
dllimports.NewEnergyImport("CEFDisplayRef_GetCount", 0),
dllimports.NewEnergyImport("CEFDisplayRef_GetAlls", 0),
dllimports.NewEnergyImport("CEFDisplayRef_Get", 0),
dllimports.NewEnergyImport("CEFDisplayRef_ScreenPointToPixels", 0),
dllimports.NewEnergyImport("CEFDisplayRef_ScreenPointFromPixels", 0),
dllimports.NewEnergyImport("CEFDisplayRef_ScreenRectToPixels", 0),
dllimports.NewEnergyImport("CEFDisplayRef_ScreenRectFromPixels", 0),
dllimports.NewEnergyImport("CEFDisplay_ID", 0),
dllimports.NewEnergyImport("CEFDisplay_DeviceScaleFactor", 0),
dllimports.NewEnergyImport("CEFDisplay_Rotation", 0),
......
......@@ -11,7 +11,7 @@
//go:build linux
// Linux
// GTK3: Manually calling initialization
// GTK2 & GTK3: Manually calling initialization
// Other: Automatic initialization and destruction
package lclwidget
......
......@@ -10,7 +10,7 @@
//go:build !linux
// GTK3: Manually calling initialization
// GTK2 & GTK3: Manually calling initialization
// Other: Automatic initialization and destruction
package lclwidget
......
//----------------------------------------
//
// 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"
"github.com/energye/golcl/lcl"
)
// IScreen
// Two ways to obtain screen information
// They are: 1. Using LCL, 2 Using CEF
type IScreen interface {
Primary() (info Display) // Returns the primary Display.
Count() int // Returns display count
Get(index int) (info Display) // Returns Obtain brief information about the specified screen
LCLScreen() *lcl.TScreen // Use this function when using the LCL window, If using ViewFramework window under Windows, this function can also be used
VFScreen() *display // Use this function when using the CEF ViewFramework
}
// Display
// Screen brief information
type Display struct {
ID int
WorkArea TCefRect
Bounds TCefRect
Rotation int32 // Currently, LCL has not been obtained
DeviceScaleFactor float32 // Currently, LCL has not been obtained
}
type Screen struct {
window IBrowserWindow
lclScreen *lcl.TScreen
}
// LCLScreen
// Use this function when using the LCL window
// If using VF windows under Windows, this function can also be used
func (m *Screen) LCLScreen() *lcl.TScreen {
if m.window == nil {
return nil
}
if m.window.IsLCL() {
if m.lclScreen == nil {
m.lclScreen = lcl.NewScreen(m.window.AsLCLBrowserWindow().BrowserWindow())
}
} else if m.window.IsViewsFramework() && common.IsWindows() {
// If using VF windows under Windows, this function can also be used
if m.lclScreen == nil {
m.lclScreen = lcl.NewScreen(m.window.AsViewsFrameworkBrowserWindow().WindowComponent())
}
}
return m.lclScreen
}
// VFScreen
// Use this function when using the CEF ViewFramework
func (m *Screen) VFScreen() *display {
if m.window == nil {
return nil
}
if m.window.IsViewsFramework() {
return &DisplayRef
}
return nil
}
// Count
// Returns all display count
func (m *Screen) Count() int {
if m.window == nil {
return 0
}
if m.window.IsLCL() {
return int(m.LCLScreen().MonitorCount())
} else if m.window.IsViewsFramework() {
return int(m.VFScreen().GetCount())
}
return 0
}
// Primary
// Returns the primary Display.
func (m *Screen) Primary() (info Display) {
if m.window.IsLCL() {
screen := m.LCLScreen()
monitor := screen.PrimaryMonitor()
if monitor == nil {
return
}
wkr := monitor.WorkareaRect()
bdr := monitor.BoundsRect()
info.ID = int(monitor.MonitorNum())
info.WorkArea = TCefRect{X: wkr.Left, Y: wkr.Top, Width: wkr.Width(), Height: wkr.Height()}
info.Bounds = TCefRect{X: bdr.Top, Y: bdr.Left, Width: bdr.Width(), Height: bdr.Height()}
screen.PrimaryMonitor()
} else if m.window.IsViewsFramework() {
screen := m.VFScreen()
monitor := screen.Primary()
if monitor == nil {
return
}
wkr := monitor.WorkArea()
bdr := monitor.Bounds()
info.ID = int(monitor.ID())
info.Rotation = monitor.Rotation()
info.DeviceScaleFactor = monitor.DeviceScaleFactor()
info.WorkArea = TCefRect{X: wkr.X, Y: wkr.Y, Width: wkr.Width, Height: wkr.Height}
info.Bounds = TCefRect{X: bdr.X, Y: bdr.Y, Width: bdr.Width, Height: bdr.Height}
}
return
}
func (m *Screen) Get(index int) (info Display) {
if m.window.IsLCL() {
screen := m.LCLScreen()
monitor := screen.Monitors(int32(index))
if monitor == nil {
return
}
wkr := monitor.WorkareaRect()
bdr := monitor.BoundsRect()
info.ID = int(monitor.MonitorNum())
info.WorkArea = TCefRect{X: wkr.Left, Y: wkr.Top, Width: wkr.Width(), Height: wkr.Height()}
info.Bounds = TCefRect{X: bdr.Top, Y: bdr.Left, Width: bdr.Width(), Height: bdr.Height()}
} else if m.window.IsViewsFramework() {
screen := m.VFScreen()
alls := screen.GetAlls()
monitor := alls.Get(uint32(index))
if monitor == nil {
return
}
wkr := monitor.WorkArea()
bdr := monitor.Bounds()
info.ID = int(monitor.ID())
info.Rotation = monitor.Rotation()
info.DeviceScaleFactor = monitor.DeviceScaleFactor()
info.WorkArea = TCefRect{X: wkr.X, Y: wkr.Y, Width: wkr.Width, Height: wkr.Height}
info.Bounds = TCefRect{X: bdr.X, Y: bdr.Y, Width: bdr.Width, Height: bdr.Height}
}
return
}
......@@ -216,12 +216,15 @@ func (m *ICefDictionaryValue) GetDouble(key string) (result float64) {
return result
}
func (m *ICefDictionaryValue) GetString(key string) string {
func (m *ICefDictionaryValue) GetString(key string) (value string) {
if !m.IsValid() {
return ""
}
r1, _, _ := imports.Proc(def.CefDictionaryValue_GetString).Call(m.Instance(), api.PascalStr(key))
return api.GoStr(r1)
val := NewTString()
imports.Proc(def.CefDictionaryValue_GetString).Call(m.Instance(), api.PascalStr(key), val.Instance())
value = val.Value()
val.Free()
return
}
func (m *ICefDictionaryValue) GetBinary(key string) *ICefBinaryValue {
......
......@@ -13,9 +13,81 @@ package cef
import (
"github.com/energye/energy/v2/cef/internal/def"
"github.com/energye/energy/v2/common/imports"
"github.com/energye/golcl/lcl/api"
"github.com/energye/golcl/lcl/types"
"unsafe"
)
// DisplayRef -> ICefDisplay
var DisplayRef display
type display struct {
alls *ICefDisplayArray
}
func (m *display) Primary() *ICefDisplay {
var result uintptr
imports.Proc(def.CEFDisplayRef_Primary).Call(uintptr(unsafe.Pointer(&result)))
if result != 0 {
return &ICefDisplay{instance: getInstance(result)}
}
return nil
}
func (m *display) NearestPoint(point *TCefPoint, inputPixelCoords bool) *ICefDisplay {
var result uintptr
imports.Proc(def.CEFDisplayRef_NearestPoint).Call(uintptr(unsafe.Pointer(point)), api.PascalBool(inputPixelCoords), uintptr(unsafe.Pointer(&result)))
if result != 0 {
return &ICefDisplay{instance: getInstance(result)}
}
return nil
}
func (m *display) MatchingBounds(point *TCefRect, inputPixelCoords bool) *ICefDisplay {
var result uintptr
imports.Proc(def.CEFDisplayRef_MatchingBounds).Call(uintptr(unsafe.Pointer(point)), api.PascalBool(inputPixelCoords), uintptr(unsafe.Pointer(&result)))
if result != 0 {
return &ICefDisplay{instance: getInstance(result)}
}
return nil
}
func (m *display) GetCount() uint32 {
r1, _, _ := imports.Proc(def.CEFDisplayRef_GetCount).Call()
return uint32(r1)
}
func (m *display) GetAlls() *ICefDisplayArray {
if m.alls == nil {
var result uintptr
r1, _, _ := imports.Proc(def.CEFDisplayRef_GetAlls).Call(uintptr(unsafe.Pointer(&result)))
if r1 != 0 && result != 0 {
m.alls = &ICefDisplayArray{instance: getInstance(result), count: m.GetCount()}
}
}
return m.alls
}
func (m *display) ScreenPointToPixels(screenPoint *types.TPoint) (point types.TPoint) {
imports.Proc(def.CEFDisplayRef_ScreenPointToPixels).Call(uintptr(unsafe.Pointer(screenPoint)), uintptr(unsafe.Pointer(&point)))
return
}
func (m *display) ScreenPointFromPixels(pixelsPoint *types.TPoint) (point types.TPoint) {
imports.Proc(def.CEFDisplayRef_ScreenPointFromPixels).Call(uintptr(unsafe.Pointer(pixelsPoint)), uintptr(unsafe.Pointer(&point)))
return
}
func (m *display) ScreenRectToPixels(screenRect *types.TRect) (rect types.TRect) {
imports.Proc(def.CEFDisplayRef_ScreenRectToPixels).Call(uintptr(unsafe.Pointer(screenRect)), uintptr(unsafe.Pointer(&rect)))
return
}
func (m *display) ScreenRectFromPixels(pixelsRect *types.TRect) (rect types.TRect) {
imports.Proc(def.CEFDisplayRef_ScreenRectFromPixels).Call(uintptr(unsafe.Pointer(pixelsRect)), uintptr(unsafe.Pointer(&rect)))
return
}
func (m *ICefDisplay) ID() (result int64) {
if !m.IsValid() {
return 0
......@@ -24,13 +96,12 @@ func (m *ICefDisplay) ID() (result int64) {
return
}
func (m *ICefDisplay) DeviceScaleFactor() float32 {
func (m *ICefDisplay) DeviceScaleFactor() (result float32) {
if !m.IsValid() {
return 0
}
var result uintptr
imports.Proc(def.CEFDisplay_DeviceScaleFactor).Call(m.Instance(), uintptr(unsafe.Pointer(&result)))
return *(*float32)(unsafe.Pointer(result))
return
}
func (m *ICefDisplay) Rotation() int32 {
......@@ -74,3 +145,41 @@ func (m *ICefDisplay) IsValid() bool {
}
return m.instance != nil
}
func (m *ICefDisplayArray) Instance() uintptr {
return uintptr(m.instance)
}
func (m *ICefDisplayArray) Free() {
if m.instance != nil {
m.instance = nil
}
}
func (m *ICefDisplayArray) IsValid() bool {
if m == nil || m.instance == nil {
return false
}
return m.instance != nil
}
func (m *ICefDisplayArray) Get(index uint32) *ICefDisplay {
if !m.IsValid() {
return nil
}
if index < m.count {
var result uintptr
r1, _, _ := imports.Proc(def.CEFDisplayRef_Get).Call(m.Instance(), uintptr(index), uintptr(unsafe.Pointer(&result)))
if r1 != 0 && result != 0 {
return &ICefDisplay{instance: getInstance(result)}
}
}
return nil
}
func (m *ICefDisplayArray) Count() uint32 {
if !m.IsValid() {
return 0
}
return m.count
}
......@@ -191,12 +191,15 @@ func (m *ICefListValue) GetDouble(index uint32) (result float64) {
return result
}
func (m *ICefListValue) GetString(index uint32) string {
func (m *ICefListValue) GetString(index uint32) (value string) {
if !m.IsValid() {
return ""
}
r1, _, _ := imports.Proc(def.CefListValue_GetString).Call(m.Instance(), uintptr(index))
return api.GoStr(r1)
val := NewTString()
imports.Proc(def.CefListValue_GetString).Call(m.Instance(), uintptr(index), val.Instance())
value = val.Value()
val.Free()
return
}
func (m *ICefListValue) GetBinary(index uint32) *ICefBinaryValue {
......
......@@ -311,12 +311,15 @@ func (m *ICefV8Value) GetDateValue() time.Time {
return common.DDateTimeToGoDateTime(result)
}
func (m *ICefV8Value) GetStringValue() string {
func (m *ICefV8Value) GetStringValue() (value string) {
if !m.IsValid() {
return ""
}
r1, _, _ := imports.Proc(def.CefV8Value_GetStringValue).Call(m.Instance())
return api.GoStr(r1)
val := NewTString()
imports.Proc(def.CefV8Value_GetStringValue).Call(m.Instance(), val.Instance())
value = val.Value()
val.Free()
return
}
func (m *ICefV8Value) IsUserCreated() bool {
......
......@@ -51,21 +51,33 @@ func (m *ICefValue) Instance() uintptr {
}
func (m *ICefValue) IsValid() bool {
if m == nil || m.instance == nil {
return false
}
r1, _, _ := imports.Proc(def.CefValue_IsValid).Call(m.Instance())
return api.GoBool(r1)
}
func (m *ICefValue) IsOwned() bool {
if !m.IsValid() {
return false
}
r1, _, _ := imports.Proc(def.CefValue_IsOwned).Call(m.Instance())
return api.GoBool(r1)
}
func (m *ICefValue) IsReadOnly() bool {
if !m.IsValid() {
return false
}
r1, _, _ := imports.Proc(def.CefValue_IsReadOnly).Call(m.Instance())
return api.GoBool(r1)
}
func (m *ICefValue) Copy() *ICefValue {
if !m.IsValid() {
return nil
}
var result uintptr
imports.Proc(def.CefValue_Copy).Call(m.Instance(), uintptr(unsafe.Pointer(&result)))
return &ICefValue{
......@@ -74,31 +86,52 @@ func (m *ICefValue) Copy() *ICefValue {
}
func (m *ICefValue) GetType() consts.TCefValueType {
if !m.IsValid() {
return 0
}
r1, _, _ := imports.Proc(def.CefValue_GetType).Call(m.Instance())
return consts.TCefValueType(r1)
}
func (m *ICefValue) GetBool() bool {
if !m.IsValid() {
return false
}
r1, _, _ := imports.Proc(def.CefValue_GetBool).Call(m.Instance())
return api.GoBool(r1)
}
func (m *ICefValue) GetInt() int32 {
if !m.IsValid() {
return 0
}
r1, _, _ := imports.Proc(def.CefValue_GetInt).Call(m.Instance())
return int32(r1)
}
func (m *ICefValue) GetDouble() (result float64) {
if !m.IsValid() {
return 0
}
imports.Proc(def.CefValue_GetDouble).Call(m.Instance(), uintptr(unsafe.Pointer(&result)))
return result
}
func (m *ICefValue) GetString() string {
r1, _, _ := imports.Proc(def.CefValue_GetString).Call(m.Instance())
return api.GoStr(r1)
func (m *ICefValue) GetString() (value string) {
if !m.IsValid() {
return ""
}
val := NewTString()
imports.Proc(def.CefValue_GetString).Call(m.Instance(), val.Instance())
value = val.Value()
val.Free()
return
}
func (m *ICefValue) GetBinary() *ICefBinaryValue {
if !m.IsValid() {
return nil
}
var result uintptr
imports.Proc(def.CefValue_GetBinary).Call(m.Instance(), uintptr(unsafe.Pointer(&result)))
return &ICefBinaryValue{
......@@ -111,6 +144,9 @@ func (m *ICefValue) GetIBinary() types.IBinaryValue {
}
func (m *ICefValue) GetDictionary() *ICefDictionaryValue {
if !m.IsValid() {
return nil
}
var result uintptr
imports.Proc(def.CefValue_GetDictionary).Call(m.Instance(), uintptr(unsafe.Pointer(&result)))
return &ICefDictionaryValue{
......@@ -119,10 +155,16 @@ func (m *ICefValue) GetDictionary() *ICefDictionaryValue {
}
func (m *ICefValue) GetIObject() types.IObjectValue {
if !m.IsValid() {
return nil
}
return m.GetDictionary()
}
func (m *ICefValue) GetList() *ICefListValue {
if !m.IsValid() {
return nil
}
var result uintptr
imports.Proc(def.CefValue_GetList).Call(m.Instance(), uintptr(unsafe.Pointer(&result)))
return &ICefListValue{
......@@ -135,31 +177,49 @@ func (m *ICefValue) GetIArray() types.IArrayValue {
}
func (m *ICefValue) SetNull() bool {
if !m.IsValid() {
return false
}
r1, _, _ := imports.Proc(def.CefValue_SetNull).Call(m.Instance())
return api.GoBool(r1)
}
func (m *ICefValue) SetBool(value bool) bool {
if !m.IsValid() {
return false
}
r1, _, _ := imports.Proc(def.CefValue_SetBool).Call(m.Instance(), api.PascalBool(value))
return api.GoBool(r1)
}
func (m *ICefValue) SetInt(value int32) bool {
if !m.IsValid() {
return false
}
r1, _, _ := imports.Proc(def.CefValue_SetInt).Call(m.Instance(), uintptr(value))
return api.GoBool(r1)
}
func (m *ICefValue) SetDouble(value float64) bool {
if !m.IsValid() {
return false
}
r1, _, _ := imports.Proc(def.CefValue_SetDouble).Call(m.Instance(), uintptr(unsafe.Pointer(&value)))
return api.GoBool(r1)
}
func (m *ICefValue) SetString(value string) bool {
if !m.IsValid() {
return false
}
r1, _, _ := imports.Proc(def.CefValue_SetString).Call(m.Instance(), api.PascalStr(value))
return api.GoBool(r1)
}
func (m *ICefValue) SetBinary(value *ICefBinaryValue) (result bool) {
if !m.IsValid() {
return false
}
r1, _, _ := imports.Proc(def.CefValue_SetBinary).Call(m.Instance(), value.Instance())
result = api.GoBool(r1)
if result {
......@@ -172,6 +232,9 @@ func (m *ICefValue) SetBinary(value *ICefBinaryValue) (result bool) {
}
func (m *ICefValue) SetDictionary(value *ICefDictionaryValue) (result bool) {
if !m.IsValid() {
return false
}
r1, _, _ := imports.Proc(def.CefValue_SetDictionary).Call(m.Instance(), value.Instance())
result = api.GoBool(r1)
if result {
......@@ -184,6 +247,9 @@ func (m *ICefValue) SetDictionary(value *ICefDictionaryValue) (result bool) {
}
func (m *ICefValue) SetList(value *ICefListValue) (result bool) {
if !m.IsValid() {
return false
}
r1, _, _ := imports.Proc(def.CefValue_SetList).Call(m.Instance(), value.Instance())
result = api.GoBool(r1)
if result {
......
......@@ -158,7 +158,7 @@ func (m *ICefX509Certificate) GetDEREncodedIssuerChain(chainCount uint32) *TCefB
return nil
}
var result uintptr
imports.Proc(def.CefX509Certificate_GetDEREncodedIssuerChain).Call(m.Instance(), uintptr(unsafe.Pointer(&result)))
imports.Proc(def.CefX509Certificate_GetDEREncodedIssuerChain).Call(m.Instance(), uintptr(chainCount), uintptr(unsafe.Pointer(&result)))
if result != 0 {
return &TCefBinaryValueArray{count: chainCount, instance: unsafe.Pointer(result)}
}
......@@ -170,7 +170,7 @@ func (m *ICefX509Certificate) GetPEMEncodedIssuerChain(chainCount uint32) *TCefB
return nil
}
var result uintptr
imports.Proc(def.CefX509Certificate_GetPEMEncodedIssuerChain).Call(m.Instance(), uintptr(unsafe.Pointer(&result)))
imports.Proc(def.CefX509Certificate_GetPEMEncodedIssuerChain).Call(m.Instance(), uintptr(chainCount), uintptr(unsafe.Pointer(&result)))
if result != 0 {
return &TCefBinaryValueArray{count: chainCount, instance: unsafe.Pointer(result)}
}
......
......@@ -345,6 +345,14 @@ type ICefDictionaryValue struct {
listValues map[string]*ICefListValue
}
// ICefDisplayArray
// []ICefDisplayArray
type ICefDisplayArray struct {
instance unsafe.Pointer
binaryValues []*ICefDisplayArray
count uint32
}
// ICefDisplay
type ICefDisplay struct {
base TCefBaseRefCounted
......
......@@ -2,18 +2,18 @@ SET CGO_ENABLED=1
set GOARCH=386
set GOOS=windows
go build -o energy-32.exe energy.go
go build -ldflags "-s -w" -o energy-32.exe energy.go
set GOARCH=amd64
set GOOS=windows
go build -o energy-64.exe energy.go
go build -ldflags "-s -w" -o energy-64.exe energy.go
set GOARCH=amd64
set GOOS=darwin
go build -o energy-darwin-64 energy.go
go build -ldflags "-s -w" -o energy-darwin-64 energy.go
set GOARCH=amd64
set GOOS=linux
go build -o energy-linux-64 energy.go
go build -ldflags "-s -w" -o energy-linux-64 energy.go
pause
\ No newline at end of file
......@@ -22,6 +22,8 @@ var commands = []*internal.Command{
internal.CmdInstall,
internal.CmdPackage,
internal.CmdVersion,
internal.CmdSetenv,
internal.CmdEnv,
}
func main() {
......@@ -43,6 +45,10 @@ func main() {
cc.Index = 2
case "version", "v":
cc.Index = 3
case "setenv":
cc.Index = 4
case "env":
cc.Index = 5
}
command := commands[cc.Index]
if len(extraArgs) < 1 || extraArgs[len(extraArgs)-1] != "." {
......
......@@ -16,6 +16,8 @@ type CommandConfig struct {
Install Install `command:"install"`
Package Package `command:"package"`
Version Version `command:"version"`
Setenv Setenv `command:"setenv"`
Env Env `command:"env"`
}
type Install struct {
......@@ -31,6 +33,13 @@ type Package struct {
Out string `short:"o" long:"out" description:"Output directory" default:"EnergyInstallPkg"`
}
type Env struct {
}
type Setenv struct {
Path string `short:"p" long:"path" description:"Energy framework dir"`
}
type Version struct {
All bool `short:"a" long:"all" description:"show all"`
}
......
......@@ -10,10 +10,19 @@
package internal
import "runtime"
const (
cefKey = "cef"
energyKey = "energy"
download_version_config_url = "https://energy.yanghy.cn/autoconfig/edv.json"
download_extract_url = "https://energy.yanghy.cn/autoconfig/extract.json"
frameworkCache = "EnergyFrameworkDownloadCache"
ENERGY_HOME_KEY = "ENERGY_HOME"
)
const (
isWindows = runtime.GOOS == "windows" //support
isLinux = runtime.GOOS == "linux" //support
isDarwin = runtime.GOOS == "darwin" //support
)
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
package internal
import (
"os"
)
var CmdEnv = &Command{
UsageLine: "env",
Short: "Get energy framework development environment",
Long: `
Get the Framework pointed to by the ENERGY_HOME development environment variable
. Execute default command
`,
}
func init() {
CmdEnv.Run = runGetEnv
}
func runGetEnv(c *CommandConfig) error {
envPath := os.Getenv(ENERGY_HOME_KEY)
println("ENERGY_HOME_KEY", envPath)
return nil
}
......@@ -76,7 +76,6 @@ func (m *IDE) OnFormCreate(sender lcl.IObject) {
lcl.Application.Icon().LoadFromFSFile("resources/icon.ico")
m.forms = make([]*IDEForm, 0, 0)
m.SetCaption(fmt.Sprintf(Title, Version))
m.SetPosition(types.PoScreenCenter)
m.SetWidth(1200)
m.SetHeight(800)
m.SetDoubleBuffered(true)
......@@ -157,6 +156,7 @@ func (m *IDE) OnFormCreate(sender lcl.IObject) {
install(m.CreateForm("安装程序-安装过程界面"))
install(m.CreateForm("安装程序-完成界面"))
install(m.CreateForm("安装程序-卸载界面"))
m.ScreenCenter()
}
func (m *IDE) addForm(form *IDEForm) int {
......
......@@ -18,16 +18,12 @@ import (
"encoding/json"
"fmt"
progressbar "github.com/energye/energy/v2/cmd/internal/progress-bar"
"github.com/energye/energy/v2/common"
"github.com/energye/energy/v2/consts"
"github.com/energye/golcl/tools/command"
"io"
"io/fs"
"io/ioutil"
"net/http"
"net/url"
"os"
"path"
"path/filepath"
"runtime"
"strconv"
......@@ -65,9 +61,40 @@ func init() {
CmdInstall.Run = runInstall
}
const (
GTK3 = iota + 1
GTK2
)
// https://cef-builds.spotifycdn.com/cef_binary_107.1.11%2Bg26c0b5e%2Bchromium-107.0.5304.110_windows64.tar.bz2
// 运行安装
func runInstall(c *CommandConfig) error {
var (
gtk int
)
if isLinux { // linux, gtk2, gtk3 install
var gtksel = []string{"", "GTK3", "GTK2"}
println(`
Your current installation environment is Linux and there are two GTK solutions available, namely GTK2 GTK3
GTK2: Supports LCL window and can use various LCL controls. The CEF<=106 version supports by default
GTK3: does not support LCL windows and most LCL controls, CEF>=107 version default support
Enter the number to select the installation support for different versions of GTK framework
Number Description
1: GTK3
2: GTK2`)
// 输入选择GTK支持框架
for {
print("Please enter the number: ")
fmt.Scan(&gtk)
if gtk == GTK3 || gtk == GTK2 {
break
} else {
println("Number input error, please re-enter. Only 1: GTK3 or 2: GTK2 are supported")
}
}
println("Support framework selected:", gtksel[gtk])
}
if c.Install.Path == "" {
c.Install.Path = c.Wd
}
......@@ -112,8 +139,19 @@ func runInstall(c *CommandConfig) error {
println("Invalid version number:", c.Install.Version)
os.Exit(1)
}
var versionCEF = version["cef"].(string)
var versionENERGY = version["energy"].(string)
var (
versionCEF, versionENERGY string
)
if isLinux {
if gtk == GTK3 {
versionCEF = ToRNilString(version["cef"], "")
} else {
versionCEF = ToRNilString(version["cefgtk2"], "")
}
} else {
versionCEF = ToString(version["cef"])
}
versionENERGY = version["energy"].(string)
var downloadURL map[string]interface{}
if c.Install.Download == "gitee" {
downloadURL = edv["gitee"].(map[string]interface{})
......@@ -124,7 +162,7 @@ func runInstall(c *CommandConfig) error {
os.Exit(1)
}
libCEFOS, isSupport := cefOS()
libEnergyOS, isSupport := energyOS()
libEnergyOS, isSupport := energyOS(gtk)
var downloadCefURL = downloadURL["cefURL"].(string)
var downloadEnergyURL = downloadURL["energyURL"].(string)
downloadCefURL = strings.ReplaceAll(downloadCefURL, "{version}", versionCEF)
......@@ -194,93 +232,24 @@ func runInstall(c *CommandConfig) error {
println("Remove file", rmFile)
os.Remove(rmFile)
}
setEnergyHomeEnv(consts.ENERGY_HOME_KEY, installPathName)
println("\n", CmdInstall.Short, "SUCCESS \nVersion:", c.Install.Version)
setEnergyHomeEnv(ENERGY_HOME_KEY, installPathName)
println("\n", CmdInstall.Short, "SUCCESS \nVersion:", c.Install.Version, "=>", versionENERGY)
return nil
}
func setEnergyHomeEnv(key, value string) {
println("\nSetting environment Variables to ", value)
cmd := command.NewCMD()
cmd.MessageCallback = func(s []byte, e error) {
fmt.Println("CMD", s, " error", e)
}
if common.IsWindows() {
var args = []string{"/c", "setx", key, value}
cmd.Command("cmd.exe", args...)
} else {
var envFiles []string
var energyHomeKey = fmt.Sprintf("export %s", key)
var energyHome = fmt.Sprintf("export %s=%s", key, value)
if common.IsLinux() {
envFiles = []string{".profile", ".zshrc", ".bashrc"}
} else if common.IsDarwin() {
envFiles = []string{".profile", ".zshrc", ".bash_profile"}
}
for _, file := range envFiles {
var fp = path.Join(consts.HomeDir, file)
cmd.Command("touch", fp)
f, err := os.OpenFile(fp, os.O_RDWR|os.O_APPEND, 0666)
if err == nil {
var oldContent string
if contentBytes, err := ioutil.ReadAll(f); err == nil {
content := string(contentBytes)
oldContent = content
var lines = strings.Split(content, "\n")
var exist = false
for i := 0; i < len(lines); i++ {
line := lines[i]
if strings.Index(line, energyHomeKey) == 0 {
content = strings.ReplaceAll(content, line, energyHome)
exist = true
}
}
if exist {
if err := f.Close(); err == nil {
var oldWrite = func() {
if f, err = os.OpenFile(fp, os.O_RDWR, 0666); err == nil {
f.WriteString(oldContent)
f.Close()
}
}
if newOpenFile, err := os.OpenFile(fp, os.O_RDWR|os.O_TRUNC, 0666); err == nil {
if _, err := newOpenFile.WriteString(content); err == nil {
newOpenFile.Close()
} else {
newOpenFile.Close()
oldWrite()
}
} else {
oldWrite()
}
}
} else {
f.WriteString("\n")
f.WriteString(energyHome)
f.WriteString("\n")
}
} else {
f.Close()
}
}
}
}
cmd.Close()
}
func cefOS() (string, bool) {
if common.IsWindows() { // windows arm for 64 bit, windows for 32/64 bit
if isWindows { // windows arm for 64 bit, windows for 32/64 bit
if runtime.GOARCH == "arm64" {
return "windowsarm64", true
}
return fmt.Sprintf("windows%d", strconv.IntSize), true
} else if common.IsLinux() { //linux for 64 bit
} else if isLinux { //linux for 64 bit
if runtime.GOARCH == "arm64" {
return "linuxarm64", true
} else if runtime.GOARCH == "amd64" {
return "linux64", true
}
} else if common.IsDarwin() { // macosx for 64 bit
} else if isDarwin { // macosx for 64 bit
if runtime.GOARCH == "arm64" {
return "macosarm64", true
} else if runtime.GOARCH == "amd64" {
......@@ -291,12 +260,15 @@ func cefOS() (string, bool) {
return fmt.Sprintf("%v %v", runtime.GOOS, runtime.GOARCH), false
}
func energyOS() (string, bool) {
if common.IsWindows() {
func energyOS(gtk int) (string, bool) {
if isWindows {
return fmt.Sprintf("Windows %d bits", strconv.IntSize), true
} else if common.IsLinux() {
return "Linux x86 64 bits", true
} else if common.IsDarwin() {
} else if isLinux {
if gtk == GTK3 {
return "Linux x86 64 bits", true
}
return "Linux GTK2 x86 64 bits", true
} else if isDarwin {
return "MacOSX x86 64 bits", true
}
//not support
......
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
package internal
import (
"errors"
"fmt"
"github.com/energye/golcl/energy/homedir"
"github.com/energye/golcl/tools/command"
"io/ioutil"
"os"
"path"
"strings"
)
var CmdSetenv = &Command{
UsageLine: "setenv -p [path]",
Short: "Set energy framework development environment",
Long: `
-p Set the Framework pointed to by the ENERGY_HOME development environment variable
. Execute default command
`,
}
func init() {
CmdSetenv.Run = runSetenv
}
func runSetenv(c *CommandConfig) error {
if c.Setenv.Path == "" {
return errors.New("ERROR: ENERGY environment variable, command line argument [-p] directory to empty")
}
if !IsExist(c.Setenv.Path) {
return errors.New("Directory [" + c.Setenv.Path + "] does not exist")
}
setEnergyHomeEnv(ENERGY_HOME_KEY, c.Setenv.Path)
println("SUCCESS")
return nil
}
func setEnergyHomeEnv(key, value string) {
println("\nSetting environment Variables to ", value)
cmd := command.NewCMD()
cmd.MessageCallback = func(s []byte, e error) {
fmt.Println("CMD", s, " error", e)
}
defer cmd.Close()
if isWindows {
var args = []string{"/c", "setx", key, value}
cmd.Command("cmd.exe", args...)
} else {
var envFiles []string
var energyHomeKey = fmt.Sprintf("export %s", key)
var energyHome = fmt.Sprintf("export %s=%s", key, value)
if isLinux {
envFiles = []string{".profile", ".zshrc", ".bashrc"}
} else if isDarwin {
envFiles = []string{".profile", ".zshrc", ".bash_profile"}
}
homeDir, _ := homedir.Dir()
for _, file := range envFiles {
var fp = path.Join(homeDir, file)
cmd.Command("touch", fp)
f, err := os.OpenFile(fp, os.O_RDWR|os.O_APPEND, 0666)
if err == nil {
var oldContent string
if contentBytes, err := ioutil.ReadAll(f); err == nil {
content := string(contentBytes)
oldContent = content
var lines = strings.Split(content, "\n")
var exist = false
for i := 0; i < len(lines); i++ {
line := lines[i]
if strings.Index(line, energyHomeKey) == 0 {
content = strings.ReplaceAll(content, line, energyHome)
exist = true
}
}
if exist {
if err := f.Close(); err == nil {
var oldWrite = func() {
if f, err = os.OpenFile(fp, os.O_RDWR, 0666); err == nil {
f.WriteString(oldContent)
f.Close()
}
}
if newOpenFile, err := os.OpenFile(fp, os.O_RDWR|os.O_TRUNC, 0666); err == nil {
if _, err := newOpenFile.WriteString(content); err == nil {
newOpenFile.Close()
} else {
newOpenFile.Close()
oldWrite()
}
} else {
oldWrite()
}
}
} else {
f.WriteString("\n")
f.WriteString(energyHome)
f.WriteString("\n")
}
} else {
f.Close()
}
}
}
}
}
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
package internal
import "os"
func ToString(v interface{}) string {
if v == nil {
return ""
}
return v.(string)
}
func ToRNilString(v interface{}, new string) string {
if v == nil {
return new
}
return v.(string)
}
func IsExist(path string) bool {
_, err := os.Stat(path)
if err != nil {
if os.IsExist(err) {
return true
} else if os.IsNotExist(err) {
return false
}
return false
}
return true
}
......@@ -55,9 +55,13 @@ func runVersion(c *CommandConfig) error {
var version = keys[i]
var ver = versionList[version].(map[string]interface{})
if c.Version.All {
cef := ToRNilString(ver["cef"], "--")
cefgtk2 := ToRNilString(ver["cefgtk2"], "--")
energy := ToRNilString(ver["energy"], "--")
println(" ", version, fmt.Sprintf(`
ENERGY: %s
CEF: %s
ENERGY: %s`, ver["cef"].(string), ver["energy"].(string)))
CEF-GTK2: %s`, energy, cef, cefgtk2))
} else {
println(" ", version)
}
......
......@@ -12,6 +12,9 @@
>> 在运行配置中 `Go tool arguments` 中配置 `-tags="tempdll"`
> 3. `TempDLL` 全局变量配置`liblcl.xx`动态库保存目录
> 4. `TempDLL` 全局变量根据编译参数`-tags="tempdll"`动态初始化
> 5. `Linux`: 需要额外增加编译选项 `gtk[2,3]` 取决于你使用的 energy 支持框架
>> 1. gtk3: `-tags="tempdll gtk3"`
>> 2. gtk2: `-tags="tempdll gtk2"`
```go
// TempDllDIR
// DLL存放目录
......
### 生成 liblcl 到 xx.go 字节数组发版包
已规定好的命名规则和文件目录
1. 压缩包
2. 文件目录
### 目录
当前系统用户目录/golcl/
### 命名
#### 文件
所属目录: /xxx/用户目录/golcl/
规则
| liblcl 文件目录 | Go 字节数组 |
|----------------------------|----------------------------|
| win32/liblcl.dll | liblcl_windows_386.go |
| win64/liblcl.dll | liblcl_windows_amd64.go |
| macos64-cocoa/liblcl.dylib | liblcl_darwin_amd64.go |
| linux64-gtk3/liblcl.so | liblcl_gtk3_linux_amd64.go |
| linux64-gtk2/liblcl.so | liblcl_gtk2_linux_amd64.go |
\ 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 (
......@@ -60,37 +70,37 @@ func main() {
for _, ff := range zz.File {
//fmt.Println(ff.Name)
switch ff.Name {
//case "linux64-gtk2/liblcl.so":
// genresByte(readZipData(ff), filepath.Join(libLCLBinResDir, "liblcl_linux_amd64.go"))
case "linux64-gtk3/liblcl.so":
genresByte(readZipData(ff), filepath.Join(libLCLBinResDir, "liblcl_linux_amd64.go"))
case "win32/liblcl.dll":
genresByte(readZipData(ff), filepath.Join(libLCLBinResDir, "liblcl_windows_386.go"))
genresByte(readZipData(ff), "windows", filepath.Join(libLCLBinResDir, "liblcl_windows_386.go"))
case "win64/liblcl.dll":
genresByte(readZipData(ff), filepath.Join(libLCLBinResDir, "liblcl_windows_amd64.go"))
genresByte(readZipData(ff), "windows", filepath.Join(libLCLBinResDir, "liblcl_windows_amd64.go"))
case "macos64-cocoa/liblcl.dylib":
genresByte(readZipData(ff), filepath.Join(libLCLBinResDir, "liblcl_darwin_amd64.go"))
genresByte(readZipData(ff), "darwin", filepath.Join(libLCLBinResDir, "liblcl_darwin_amd64.go"))
case "linux64-gtk3/liblcl.so":
genresByte(readZipData(ff), "linux && gtk3", filepath.Join(libLCLBinResDir, "liblcl_gtk3_linux_amd64.go"))
case "linux64-gtk2/liblcl.so":
genresByte(readZipData(ff), "linux && gtk2", filepath.Join(libLCLBinResDir, "liblcl_gtk2_linux_amd64.go"))
}
}
} else {
// windows 32
genresFile(filepath.Join(liblclPath, "win32", "liblcl.dll"), filepath.Join(libLCLBinResDir, "liblcl_windows_386.go"))
genresFile(filepath.Join(liblclPath, "win32", "liblcl.dll"), "windows", filepath.Join(libLCLBinResDir, "liblcl_windows_386.go"))
// windows 64
genresFile(filepath.Join(liblclPath, "win64", "liblcl.dll"), filepath.Join(libLCLBinResDir, "liblcl_windows_amd64.go"))
// linux 64 gtk2
//genresFile(filepath.Join(liblclPath, "linux64-gtk2", "liblcl.so"), filepath.Join(libLCLBinResDir, "liblcl_linux_amd64.go"))
// linux 64 gtk3
genresFile(filepath.Join(liblclPath, "linux64-gtk3", "liblcl.so"), filepath.Join(libLCLBinResDir, "liblcl_linux_amd64.go"))
genresFile(filepath.Join(liblclPath, "win64", "liblcl.dll"), "windows", filepath.Join(libLCLBinResDir, "liblcl_windows_amd64.go"))
// macos cocoa
genresFile(filepath.Join(liblclPath, "macos64-cocoa", "liblcl.dylib"), filepath.Join(libLCLBinResDir, "liblcl_darwin_amd64.go"))
genresFile(filepath.Join(liblclPath, "macos64-cocoa", "liblcl.dylib"), "darwin", filepath.Join(libLCLBinResDir, "liblcl_darwin_amd64.go"))
// linux 64 gtk3
genresFile(filepath.Join(liblclPath, "linux64-gtk3", "liblcl.so"), "linux && gtk3", filepath.Join(libLCLBinResDir, "liblcl_gtk3_linux_amd64.go"))
// linux 64 gtk2
genresFile(filepath.Join(liblclPath, "linux64-gtk2", "liblcl.so"), "linux && gtk2", filepath.Join(libLCLBinResDir, "liblcl_gtk2_linux_amd64.go"))
}
}
// 生成字节的单元
func genresFile(fileName, newFileName string) {
func genresFile(fileName, tags, newFileName string) {
bs, err := ioutil.ReadFile(fileName)
if err == nil {
genresByte(bs, newFileName)
genresByte(bs, tags, newFileName)
} else {
fmt.Println("生成字节Go文件:", newFileName, "Error:", err)
}
......@@ -137,7 +147,7 @@ func zlibCompress(input []byte) ([]byte, error) {
return in.Bytes(), nil
}
func genresByte(input []byte, newFileName string) {
func genresByte(input []byte, tags, newFileName string) {
fmt.Println("genFile: ", newFileName)
if len(input) == 0 {
fmt.Println("000000")
......@@ -152,6 +162,9 @@ func genresByte(input []byte, newFileName string) {
panic(err)
}
code := bytes.NewBuffer(nil)
code.WriteString("//go:build ")
code.WriteString(tags)
code.WriteString("\r\n\r\n")
code.WriteString("package liblclbinres")
code.WriteString("\r\n\r\n")
code.WriteString(fmt.Sprintf("const CRC32Value uint32 = 0x%x\r\n\r\n", crc32Val))
......
......@@ -1580,3 +1580,14 @@ const (
CEF_TFC_DELETE
CEF_TFC_SELECT_ALL
)
// UI tool classes used
type UITool int8
const (
UitInvalid UITool = iota - 1 // invalid
UitWin32 // windows
UitGtk2 // linux
UitGtk3 // linux
UitCocoa // macos
)
......@@ -46,7 +46,7 @@ func syso() error {
syso := winRes.NewSYSO()
// 设置命令行执行目录, 该目录是要生成图标的应用根目录
// 资源在 resources 目录中读取
syso.CMDDir = filepath.Join(wd(), "example", "lib-checkupdate")
syso.CMDDir = filepath.Join(wd(), "example", "control")
syso.IconName = "icon.ico"
return syso.RC()
}
package main
import (
"fmt"
"github.com/energye/energy/v2/example/build-examples/syso"
"github.com/energye/golcl/tools/command"
"io/ioutil"
"os"
"path/filepath"
"runtime"
)
const (
isWindows = runtime.GOOS == "windows" //support
isLinux = runtime.GOOS == "linux" //support
isDarwin = runtime.GOOS == "darwin" //support
)
func main() {
wd, _ := os.Getwd()
println("current:", wd)
dist := filepath.Join(wd, "example", "dist")
if !isExist(dist) {
os.MkdirAll(dist, os.ModePerm)
}
examples := []string{"context-menu", "control", "cookie", "cookie-manager", "custom-drag-window", "dev-tools",
"dom-visitor", "download", "drag-file", "execute-dev-tools-method", "execute-javascript", "flash-for-cef-v87",
"frameless", "i18n", "internal-http-server", "ipc-on-emit/go-composite-type", "ipc-on-emit/go-to-js", "ipc-on-emit/js-to-go",
"key-event", "lib-checkupdate", "load-html-url",
"msgbox", "osr/linux", "osr/windows", "popup-sub-window", "print-pdf", "process-type", "proxy", "response-filter",
"scheme", "screen", "search-text", "simple", "sub-process/main-process", "sub-process/sub-process", "sys-dialog",
"sys-menu", "tempdll", "view-source", "vue",
"webkit-register", "zoom"}
var (
ext string
ldflags string
)
if isWindows {
examples = append(examples, "windows/custom-browser-create", "windows/transparent")
examples = append(examples, "tray/lclceftray", "tray/lcltray", "tray/systray", "tray/lclvftray")
ext = ".exe"
ldflags = `-H windowsgui -s -w`
} else if isLinux || isDarwin {
examples = append(examples, "tray/lcltray", "tray/systray")
ldflags = `-s -w`
}
cmd := command.NewCMD()
for i, example := range examples {
dir := filepath.Join(wd, "example", example)
if isExist(dir) {
cmd.Dir = dir
copySyso(dir)
out := filepath.Join(dist, example+ext)
println("build example", example, fmt.Sprintf("%d/%d", i+1, len(examples)), "\n\tbuild-dir:", dir, "\n\tout-dir:", out)
cmd.Command("go", "build", "-ldflags", ldflags, "-o", out, `-tags=tempdll`)
removeSyso(dir)
println()
} else {
println("error not found:", dir)
println()
}
}
println("build end.")
if isWindows {
print(`Build sample completed, do you want to use upx tool for compression
Need to install upx compression tool: https://github.com/upx/upx/releases
Input 1 IS: `)
var useUPX string
fmt.Scan(&useUPX)
if useUPX == "1" {
for i, example := range examples {
filePath := filepath.Join(dist, example+ext)
if isExist(filePath) {
println("upx compression", example, fmt.Sprintf("%d/%d", i+1, len(examples)), "\n\tpath:", filePath)
cmd.Command("upx", filePath) // upx 压缩
println()
} else {
println("error not found:", filePath)
println()
}
}
} else {
println("upx exit")
}
println("upx end.")
}
cmd.Close()
}
func upx() {
}
func isExist(path string) bool {
_, err := os.Stat(path)
if err != nil {
if os.IsExist(err) {
return true
} else if os.IsNotExist(err) {
return false
}
return false
}
return true
}
func sysoname() string {
if runtime.GOARCH == "amd64" {
return "example_windows_amd64.syso"
} else if runtime.GOARCH == "386" {
return "example_windows_386.syso"
}
return ""
}
func copySyso(dir string) {
if !syso.Syso {
return
}
if sysoname() != "" {
out := filepath.Join(dir, sysoname())
if runtime.GOARCH == "amd64" {
ioutil.WriteFile(out, syso.SysoBytesx64, 0666)
} else if runtime.GOARCH == "386" {
ioutil.WriteFile(out, syso.SysoBytes386, 0666)
}
}
}
func removeSyso(dir string) {
if !syso.Syso {
return
}
if sysoname() != "" {
file := filepath.Join(dir, sysoname())
if runtime.GOARCH == "amd64" {
os.Remove(file)
} else if runtime.GOARCH == "386" {
os.Remove(file)
}
}
}
//go:build !windows
package syso
const (
Syso = false
)
var SysoBytesAMD64 []byte
var SysoBytes386 []byte
此差异已折叠。
此差异已折叠。
......@@ -21,7 +21,7 @@ func main() {
cefApp := cef.NewApplication()
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "http://localhost:22022/index.html"
if common.IsLinux() {
if common.IsLinux() && cefApp.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......@@ -59,7 +59,7 @@ func main() {
radioDefault2Check consts.MenuId
)
//右键弹出菜单
event.SetOnBeforeContextMenu(func(sender lcl.IObject, browser *cef.ICefBrowser, frame *cef.ICefFrame, params *cef.ICefContextMenuParams, model *cef.ICefMenuModel) {
event.SetOnBeforeContextMenu(func(sender lcl.IObject, browser *cef.ICefBrowser, frame *cef.ICefFrame, params *cef.ICefContextMenuParams, model *cef.ICefMenuModel) bool {
//既然是自定义,当然要去除之前事先定义好的
model.Clear()
//开始创建菜单,每个菜单项都有自己的ID, 所以要先定义一个能保存这些菜单项的ID的变量
......@@ -122,6 +122,7 @@ func main() {
radioDefault2Check = menuIdRadio201
}
model.SetChecked(radioDefault2Check, true)
return true
})
//右键菜单项命令
event.SetOnContextMenuCommand(func(sender lcl.IObject, browser *cef.ICefBrowser, frame *cef.ICefFrame, params *cef.ICefContextMenuParams, menuId consts.MenuId, eventFlags uint32, result *bool) {
......
......@@ -19,11 +19,11 @@ func main() {
//全局初始化 每个应用都必须调用的
cef.GlobalInit(&libs, &resources)
//创建应用
cefApp := cef.NewApplication()
cefApp.SetEnableGPU(true)
app := cef.NewApplication()
app.SetEnableGPU(true)
//主进程窗口
src.MainBrowserWindow()
src.MainBrowserWindow(app)
//运行应用
cef.Run(cefApp)
cef.Run(app)
}
......@@ -10,7 +10,7 @@ import (
)
//主浏览器窗口
func MainBrowserWindow() {
func MainBrowserWindow(app *cef.TCEFApplication) {
//只有启动主进程才会继续执行
if !process.Args.IsMain() {
return
......@@ -23,7 +23,7 @@ func MainBrowserWindow() {
//窗口宽高
cef.BrowserWindow.Config.Width = 1024
cef.BrowserWindow.Config.Height = 768
if common.IsLinux() {
if common.IsLinux() && app.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......@@ -35,34 +35,37 @@ func MainBrowserWindow() {
cef.BrowserWindow.Config.SetChromiumConfig(config)
//创建窗口时的回调函数 对浏览器事件设置,和窗口属性组件等创建和修改
cef.BrowserWindow.SetBrowserInit(func(event *cef.BrowserEvent, window cef.IBrowserWindow) {
if window.IsLCL() {
//在窗体初始化时创建窗口内的组件
back, forward, stop, refresh, progressLabel, addr := controlUI(window.AsLCLBrowserWindow().BrowserWindow())
//页面加载处理进度
event.SetOnLoadingProgressChange(func(sender lcl.IObject, browser *cef.ICefBrowser, progress float64) {
//linux 更新UI组件必须使用 QueueAsyncCall 主线程异步同步
cef.QueueAsyncCall(func(id int) {
//参数-进度
progressLabel.SetCaption(fmt.Sprintf("%v", progress*100))
})
if window.IsViewsFramework() {
return
}
//if window.IsLCL() {
//在窗体初始化时创建窗口内的组件
back, forward, stop, refresh, progressLabel, addr := controlUI(window.AsLCLBrowserWindow().BrowserWindow())
//页面加载处理进度
event.SetOnLoadingProgressChange(func(sender lcl.IObject, browser *cef.ICefBrowser, progress float64) {
//linux 更新UI组件必须使用 QueueAsyncCall 主线程异步同步
cef.QueueAsyncCall(func(id int) {
//参数-进度
progressLabel.SetCaption(fmt.Sprintf("%v", progress*100))
})
//页面加载状态,根据状态判断是否加载完成,和是否可前进后退
event.SetOnLoadingStateChange(func(sender lcl.IObject, browser *cef.ICefBrowser, isLoading, canGoBack, canGoForward bool) {
//linux 更新UI组件必须使用 QueueAsyncCall 主线程异步同步
cef.QueueAsyncCall(func(id int) {
//控制按钮状态
stop.SetEnabled(isLoading)
refresh.SetEnabled(!isLoading)
back.SetEnabled(canGoBack)
forward.SetEnabled(canGoForward)
})
})
//页面加载状态,根据状态判断是否加载完成,和是否可前进后退
event.SetOnLoadingStateChange(func(sender lcl.IObject, browser *cef.ICefBrowser, isLoading, canGoBack, canGoForward bool) {
//linux 更新UI组件必须使用 QueueAsyncCall 主线程异步同步
cef.QueueAsyncCall(func(id int) {
//控制按钮状态
stop.SetEnabled(isLoading)
refresh.SetEnabled(!isLoading)
back.SetEnabled(canGoBack)
forward.SetEnabled(canGoForward)
})
event.SetOnAddressChange(func(sender lcl.IObject, browser *cef.ICefBrowser, frame *cef.ICefFrame, url string) {
cef.QueueAsyncCall(func(id int) {
addr.SetText(url)
})
})
event.SetOnAddressChange(func(sender lcl.IObject, browser *cef.ICefBrowser, frame *cef.ICefFrame, url string) {
cef.QueueAsyncCall(func(id int) {
addr.SetText(url)
})
}
})
//}
})
}
......
......@@ -22,7 +22,7 @@ func main() {
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "https://www.baidu.com"
cef.BrowserWindow.Config.Title = "Energy - cookie-manager"
if common.IsLinux() {
if common.IsLinux() && app.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......
......@@ -27,7 +27,7 @@ func main() {
//主窗口的配置
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "http://localhost:22022/cookie.html"
if common.IsLinux() {
if common.IsLinux() && cefApp.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......
......@@ -15,7 +15,7 @@ func main() {
cef.GlobalInit(nil, &resources)
app := cef.NewApplication()
cef.BrowserWindow.Config.Url = "http://localhost:22022/index.html"
if common.IsLinux() {
if common.IsLinux() && app.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......
......@@ -19,8 +19,6 @@ import (
"github.com/energye/energy/v2/logger"
"github.com/energye/energy/v2/pkgs/assetserve"
"github.com/energye/golcl/lcl"
"os"
"path"
)
//go:embed resources
......@@ -44,40 +42,42 @@ func main() {
cef.BrowserWindow.SetBrowserInit(func(event *cef.BrowserEvent, window cef.IBrowserWindow) {
//window.DisableResize()
window.SetCenterWindow(true)
window.SetTitle("这里改变了窗口标题")
window.SetSize(1024, 900)
fmt.Println("cef.BrowserWindow.SetViewFrameBrowserInit", window)
fmt.Println("LCL", window.AsLCLBrowserWindow(), "VF", window.AsViewsFrameworkBrowserWindow())
window.AsViewsFrameworkBrowserWindow().SetOnWindowCreated(func(sender lcl.IObject, window *cef.ICefWindow) {
fmt.Println("WindowCreated.window", window.WindowAppIcon().Width(), window.WindowAppIcon().Height())
image := cef.ImageRef.New()
cw, _ := os.Getwd()
cw = path.Join(cw, "example", "dev-test", "vf-browser", "resources", "icon.png")
byt, err := os.ReadFile(cw)
fmt.Println("image icon.png", len(byt), err)
image.AddPng(1.2, byt)
fmt.Println("image", image.Width(), image.Height())
})
//window.SetTitle("这里改变了窗口标题")
//window.SetSize(1024, 900)
//fmt.Println("cef.BrowserWindow.SetViewFrameBrowserInit", window)
//fmt.Println("LCL", window.AsLCLBrowserWindow(), "VF", window.AsViewsFrameworkBrowserWindow())
//window.AsViewsFrameworkBrowserWindow().SetOnWindowCreated(func(sender lcl.IObject, window *cef.ICefWindow) {
// fmt.Println("WindowCreated.window", window.WindowAppIcon().Width(), window.WindowAppIcon().Height())
// image := cef.ImageRef.New()
// cw, _ := os.Getwd()
// cw = path.Join(cw, "example", "dev-test", "vf-browser", "resources", "icon.png")
// byt, err := os.ReadFile(cw)
// fmt.Println("image icon.png", len(byt), err)
// image.AddPng(1.2, byt)
// fmt.Println("image", image.Width(), image.Height())
//})
event.SetOnBeforePopup(func(sender lcl.IObject, browser *cef.ICefBrowser, frame *cef.ICefFrame, beforePopupInfo *cef.BeforePopupInfo, popupWindow cef.IBrowserWindow, noJavascriptAccess *bool) bool {
fmt.Println("IsViewsFramework:", popupWindow.IsViewsFramework())
popupWindow.SetTitle("修改了标题: " + beforePopupInfo.TargetUrl)
popupWindow.EnableResize()
popupWindow.DisableMaximize()
popupWindow.DisableResize()
popupWindow.DisableMinimize()
//popupWindow.SetTitle("修改了标题: " + beforePopupInfo.TargetUrl)
//popupWindow.EnableResize()
//popupWindow.DisableMaximize()
//popupWindow.DisableResize()
//popupWindow.DisableMinimize()
popupWindow.SetSize(800, 600)
browserWindow := popupWindow.AsViewsFrameworkBrowserWindow()
browserWindow.SetOnWindowCreated(func(sender lcl.IObject, window *cef.ICefWindow) {
fmt.Println("popupWindow.SetOnWindowCreated", window.WindowAppIcon())
})
//browserWindow.SetOnGetInitialBounds(func(sender lcl.IObject, window *cef.ICefWindow, aResult *cef.TCefRect) {
// fmt.Println("popupWindow.SetOnGetInitialBounds", *aResult)
browserWindow.Chromium().Config().SetEnableMenu(false)
//browserWindow.SetOnWindowCreated(func(sender lcl.IObject, window *cef.ICefWindow) {
// fmt.Println("popupWindow.SetOnWindowCreated", window.WindowAppIcon())
//})
//browserWindow.BrowserWindow().CreateTopLevelWindow()
//browserWindow.BrowserWindow().HideTitle()
fmt.Println("browserWindow:", browserWindow, browserWindow.WindowComponent().WindowHandle())
////browserWindow.SetOnGetInitialBounds(func(sender lcl.IObject, window *cef.ICefWindow, aResult *cef.TCefRect) {
//// fmt.Println("popupWindow.SetOnGetInitialBounds", *aResult)
////})
////browserWindow.BrowserWindow().CreateTopLevelWindow()
browserWindow.BrowserWindow().HideTitle()
//fmt.Println("browserWindow:", browserWindow, browserWindow.WindowComponent().WindowHandle())
return false
})
return
window.AsViewsFrameworkBrowserWindow().WindowComponent().SetOnWindowActivationChanged(func(sender lcl.IObject, window *cef.ICefWindow, active bool) {
fmt.Println("SetOnWindowActivationChanged", active)
})
......
//----------------------------------------
//
// 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 (
"fmt"
"github.com/energye/energy/v2/cef"
"github.com/energye/golcl/lcl"
"github.com/energye/golcl/lcl/types/colors"
)
type WindowDemo struct {
cef.LCLBrowserWindow
}
func (m *WindowDemo) OnFormCreate(sender lcl.IObject) {
fmt.Println("LCLBrowserWindow OnFormCreate")
//m.EnabledMaximize(false)
//m.EnabledMaximize(false)
//m.SetBorderStyle(types.BsNone)
m.ScreenCenter()
bufferPanel := cef.NewBufferPanel(m)
bufferPanel.SetParent(m)
bufferPanel.SetColor(colors.ClAqua)
rng := cef.TCefRange{}
rng.To = 123
rng.From = 321
characterBounds := make([]cef.TCefRect, 50)
for i := 0; i < len(characterBounds); i++ {
characterBounds[i].Width = 1000 + int32(i)
characterBounds[i].Height = 110 + int32(i)
characterBounds[i].X = 2000 + int32(i)
characterBounds[i].Y = 2101 + int32(i)
}
bufferPanel.ChangeCompositionRange(rng, characterBounds)
bufferPanel.SetForcedDeviceScaleFactor(123.11)
fmt.Println(bufferPanel.GetForcedDeviceScaleFactor())
bufferPanel.SetOnClick(func(sender lcl.IObject) {
fmt.Println("SetOnClick")
})
monitor := m.Monitor()
fmt.Println(monitor.WorkareaRect())
}
func main() {
cef.GlobalInit(nil, nil)
var window = &WindowDemo{}
lcl.RunApp(&window)
}
......@@ -25,7 +25,7 @@ func main() {
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "http://localhost:22022/dom-visitor.html"
cef.BrowserWindow.Config.Title = "Energy - dom-visitor"
if common.IsLinux() {
if common.IsLinux() && app.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......
......@@ -25,7 +25,7 @@ func main() {
//主窗口的配置
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "http://localhost:22022/download.html"
if common.IsLinux() {
if common.IsLinux() && cefApp.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......
......@@ -17,7 +17,7 @@ func main() {
cef.GlobalInit(nil, &resources)
app := cef.NewApplication()
cef.BrowserWindow.Config.Url = "http://chrome.360.cn/html5_labs/demos/dnd/"
if common.IsLinux() {
if common.IsLinux() && app.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......
......@@ -24,7 +24,7 @@ func main() {
//主窗口的配置
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "http://localhost:22022/execute-dev-tool-method.html"
if common.IsLinux() {
if common.IsLinux() && cefApp.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......
......@@ -21,7 +21,7 @@ func main() {
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "http://localhost:22022/execute-javascript.html"
cef.BrowserWindow.Config.Title = "Energy - execute-javascript"
if common.IsLinux() {
if common.IsLinux() && cefApp.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......
......@@ -29,13 +29,13 @@ func main() {
cef.GlobalInit(nil, &resources)
//创建应用
cefApp := cef.NewApplication()
// TODO 下面2个配置项用来切换使用VF或LCL窗口组件
// 下面2个配置项用来切换使用VF或LCL窗口组件
// VF = (ExternalMessagePump = false && MultiThreadedMessageLoop = false)
//cefApp.SetExternalMessagePump(false)
//cefApp.SetMultiThreadedMessageLoop(false)
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "http://localhost:22022/index.html"
if common.IsLinux() {
if common.IsLinux() && cefApp.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......@@ -44,10 +44,10 @@ func main() {
// LCL macos 隐藏标题栏后,不能调整大小
cef.BrowserWindow.Config.EnableHideCaption = true
// LCL macos 隐藏标题栏后,该选项不生效
cef.BrowserWindow.Config.EnableResize = true
//cef.BrowserWindow.Config.EnableResize = true
}
cef.BrowserWindow.Config.Title = "Energy Vue + ElementUI 示例"
cef.BrowserWindow.Config.Width = 1200
cef.BrowserWindow.Config.Width = 1366
chromiumConfig := cef.BrowserWindow.Config.ChromiumConfig()
chromiumConfig.SetEnableMenu(false) //禁用右键菜单
......@@ -61,6 +61,13 @@ func main() {
} else if state == 1 {
fmt.Println("窗口最大化/还原")
bw.Maximize()
} else if state == 3 {
fmt.Println("全屏/退出全屏")
if bw.IsFullScreen() {
bw.ExitFullScreen()
} else {
bw.FullScreen()
}
}
})
//监听窗口关闭事件
......
......@@ -77,6 +77,7 @@
<span style="-webkit-app-region: no-drag;">Energy</span>
</el-dropdown>
<span style="-webkit-app-region: no-drag;text-align: right;">
<el-button size="mini" round @click="fullScreen">全屏/退出全屏</el-button>
<el-button size="mini" round @click="minWindow">最小化</el-button>
<el-button size="mini" round @click="maxWindow">最大化</el-button>
<el-button size="mini" round @click="closeWindow">关闭</el-button>
......@@ -138,6 +139,10 @@
};
this.tableData = Array(20).fill(item)
},
fullScreen: function () {
console.log('全屏/退出全屏');
ipc.emit("window-state", [3])
},
minWindow: function () {
console.log('最小化窗口');
ipc.emit("window-state", [0])
......
......@@ -35,7 +35,7 @@ func main() {
i18n.Switch(consts.LANGUAGE_zh_CN)
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "http://localhost:22022/i18n.html"
if common.IsLinux() {
if common.IsLinux() && cefApp.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......
......@@ -20,7 +20,7 @@ func main() {
cefApp := cef.NewApplication()
//主窗口的配置
cef.BrowserWindow.Config.Title = "Energy - 内置资源和内置服务示例"
if common.IsLinux() {
if common.IsLinux() && cefApp.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......
......@@ -22,7 +22,7 @@ func main() {
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "http://localhost:22022/go-composite-type.html"
cef.BrowserWindow.Config.Title = "Energy - go-composite-type"
if common.IsLinux() {
if common.IsLinux() && cefApp.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......
......@@ -23,7 +23,7 @@ func main() {
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "http://localhost:22022/go-to-js.html"
cef.BrowserWindow.Config.Title = "Energy - go on event - js emit event"
if common.IsLinux() {
if common.IsLinux() && cefApp.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......
......@@ -21,7 +21,7 @@ func main() {
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "http://localhost:22022/js-to-go.html"
cef.BrowserWindow.Config.Title = "Energy - js on event - go emit event"
if common.IsLinux() {
if common.IsLinux() && cefApp.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......
......@@ -21,7 +21,7 @@ func main() {
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "http://localhost:22022/key-event.html"
cef.BrowserWindow.Config.Title = "Energy - Key Event"
if common.IsLinux() {
if common.IsLinux() && cefApp.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......
......@@ -42,9 +42,10 @@ var (
// form
updateForm *form.UpdateForm
version = []*dllimports.ImportTable{
dllimports.NewEnergyImport("", 0), //空导入
dllimports.NewEnergyImport("LibVersion", 0), //获取lib库的版本号
dllimports.NewEnergyImport("LibBuildVersion", 0), //获取lib库的构建工具版本
dllimports.NewEnergyImport("", 0), //空导入
dllimports.NewEnergyImport("LibVersion", 0), //获取lib库的版本号
dllimports.NewEnergyImport("LibBuildVersion", 0), //获取lib库的构建工具版本
dllimports.NewEnergyImport("Interface_CustomWidgetSetInitialization", 0), //linux lcl widget init
}
)
......@@ -88,6 +89,9 @@ func main() {
imports.SetEnergyImportDefs(version)
// 初始化golcl
inits.Init(nil, &resources)
// inits.Init 完成之后,初始化LCL控件
imports.Proc(3).Call()
// 注入资源
i18n.SetLocalFS(&resources, "resources")
//i18n.Switch(consts.LANGUAGE_en_US)
i18n.Switch(consts.LANGUAGE_zh_CN)
......@@ -121,7 +125,6 @@ func main() {
m.EnabledMaximize(false)
m.SetShowHint(true)
//m.SetFormStyle(types.FsSystemStayOnTop)
m.SetPosition(types.PoDesktopCenter)
m.SetBorderStyle(types.BsSingle)
//m.SetBorderStyle(types.BsNone)
//m.SetShowInTaskBar(types.StNever)
......@@ -324,6 +327,7 @@ func main() {
}
})
}
m.ScreenCenter()
}
// run and create update form
lcl.RunApp(&updateForm)
......
......@@ -22,7 +22,7 @@ func main() {
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = indexHtmlPath
cef.BrowserWindow.Config.Title = "Energy 本地加载html"
if common.IsLinux() {
if common.IsLinux() && cefApp.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......
......@@ -24,7 +24,7 @@ func main() {
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "http://localhost:22022/msgbox.html"
cef.BrowserWindow.Config.Title = "Energy - msgbox"
if common.IsLinux() {
if common.IsLinux() && app.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......@@ -45,24 +45,22 @@ func main() {
// 系统消息提示框目前仅能在LCL窗口组件下使用
// LCL 各种系统组件需要在UI线程中执行, 但ipc.on非UI线程
// 所以需要使用 QueueAsyncCall 包裹在UI线程中执行
if window.IsLCL() {
ipc.On("showmsgbox", func() {
cef.QueueAsyncCall(func(id int) {
lcl.ShowMessage("消息提示框")
})
ipc.On("showmsgbox", func() {
fmt.Println("showmsgbox")
window.RunOnMainThread(func() {
fmt.Println("消息提示框")
lcl.ShowMessage("消息提示框")
})
ipc.On("showmsgbox-confirm", func() {
// lcl 各种系统组件需要在UI线程中执行, 但ipc.on非UI线程
// 所以需要使用 QueueAsyncCall 包裹在UI线程中执行
cef.QueueAsyncCall(func(id int) {
if lcl.Application.MessageBox("消息", "标题", win.MB_OKCANCEL+win.MB_ICONINFORMATION) == types.IdOK {
lcl.ShowMessage("你点击了“是")
}
})
})
ipc.On("showmsgbox-confirm", func() {
// lcl 各种系统组件需要在UI线程中执行, 但ipc.on非UI线程
// 所以需要使用 QueueAsyncCall 包裹在UI线程中执行
window.RunOnMainThread(func() {
if lcl.Application.MessageBox("消息", "标题", win.MB_OKCANCEL+win.MB_ICONINFORMATION) == types.IdOK {
lcl.ShowMessage("你点击了“是")
}
})
// 使用窗口模拟一个消息提示框
}
})
})
//运行应用
......
......@@ -26,7 +26,7 @@ func main() {
cefApp := cef.NewApplication()
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "http://localhost:22022/index.html"
if common.IsLinux() {
if common.IsLinux() && cefApp.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......@@ -76,7 +76,7 @@ func main() {
}
var elliptic = func(window cef.IBrowserWindow) {
hRegion := winapi.WinCreateEllipticRgn(1, 1, 200, 200)
hRegion := winapi.WinCreateEllipticRgn(0, 0, 550, 550)
winapi.WinSetWindowRgn(types.HWND(window.Handle()), hRegion, true)
}
var transparent = func(window cef.IBrowserWindow) {
......@@ -95,17 +95,22 @@ func main() {
popupWindow.SetSize(300, 300)
popupWindow.HideTitle()
} else if strings.Index(beforePopupInfo.TargetUrl, "elliptic") > 0 {
popupWindow.SetSize(200, 200)
// windows和linux GTK2下有效果
popupWindow.WindowProperty().EnableWebkitAppRegionDClk = false
popupWindow.SetSize(550, 550)
popupWindow.HideTitle()
cef.QueueAsyncCall(func(id int) {
popupWindow.Chromium().Config().SetEnableMenu(false)
window.RunOnMainThread(func() {
// 如果使用winapi方式改变窗口,需要在主线程中运行
elliptic(popupWindow)
})
} else if strings.Index(beforePopupInfo.TargetUrl, "transparent") > 0 {
// windows和linux GTK2下有效果
popupWindow.SetSize(200, 200)
popupWindow.HideTitle()
transparent(popupWindow)
} else if strings.Index(beforePopupInfo.TargetUrl, "model_window") > 0 {
// windows和linux GTK2下有效果
popupWindow.SetSize(200, 200)
popupWindow.HideTitle()
popupWindow.WindowProperty().IsShowModel = true
......
......@@ -2,14 +2,220 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<title>popup1</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>elliptic</title>
<style>
* {
margin: 0;
padding: 0;
}
ul,
ul>li {
list-style-type: none;
}
body {
background-color: #0c020b;
}
.clock {
width: 500px;
height: 500px;
position: absolute;
margin: auto;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
.clock .mark {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
width: 100%;
height: 100%;
}
.clock .mark li {
position: absolute;
width: 6px;
height: 2px;
background: #fff;
transform-origin: 250px;
box-shadow: 0 0 10px #ffeab0;
}
.clock .mark li.bold {
width: 8px;
height: 4px;
}
.clock .numbers {
position: absolute;
left: 238px;
top: 238px;
font-size: 20px;
font-weight: 700;
line-height: 1.5;
width: 24px;
height: 24px;
text-align: center;
color: #fff;
text-shadow: 0 0 10px #ffeab0;
}
.clock .center {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
width: 24px;
height: 24px;
border-radius: 20px;
background: #ff1138;
}
.clock .hour-hand,
.clock .minute-hand,
.clock .second-hand {
box-shadow: 2px 2px 5px #ffeab0;
}
.clock .hour-hand {
position: absolute;
left: 247px;
top: 150px;
width: 6px;
height: 140px;
background: #fff;
transform-origin: 3px 100px;
}
.clock .minute-hand {
position: absolute;
left: 248px;
top: 70px;
width: 4px;
height: 220px;
background: #fff;
transform-origin: 2px 180px;
}
.clock .second-hand {
position: absolute;
left: 249px;
top: 40px;
width: 2px;
height: 280px;
background: #fff;
transform-origin: 1px 210px;
}
.clock .time {
padding: 10px;
position: absolute;
left: 260px;
top: 330px;
font-size: 12px;
font-weight: bold;
background: #110022;
color: #ff1138;
}
</style>
<script type="application/javascript">
<script type="text/javascript">
function isInt(n) {
return parseInt(n) === n;
}
function rotate(x, y, angle) {
var A, R, rad;
rad = (angle == 0 ? 270 : angle) * Math.PI / 180;
A = Math.atan2(y, x) + rad;
R = Math.sqrt(x * x + y * y);
return {
x: Math.cos(A) * R,
y: Math.sin(A) * R
};
}
function rotateElement(el, deg) {
el.style.transform = `rotate(${deg}deg)`;
}
</script>
</head>
<body style="overflow: hidden;margin: 0px;padding: 0px;width: 100%;text-align: center;background-color: #C4E3FD;">
<h1 style="-webkit-app-region: drag;">圆形页面</h1>
<body style="-webkit-app-region: drag;--webkit-app-region: drag;">
<div class="clock" style="-webkit-app-region: drag;--webkit-app-region: drag;">
<ul class="mark">
<script>
{
let i = 0;
let html = '';
while (i < 60) {
let n = i / 5 % 12;
n = n === 0 ? 12 : n;
let bold = isInt(n);
html +=
`<li class="${bold ? ' bold' : ''}" style="transform: translateY(250px) rotate(${i * 6}deg);"></li>`;
i++;
}
document.write(html);
}
</script>
</ul>
<script>
{
let angle = 30,
x = 110,
y = -190,
i = 1,
html = '';
html += `<div class="numbers" style="transform: translate(${x}px, ${y}px);">${i}</div>`;
while (i++ < 12) {
let pos = rotate(x, y, angle);
x = pos.x;
y = pos.y;
html += `<div class="numbers" style="transform: translate(${x}px, ${y}px);">${i}</div>`;
}
document.write(html);
}
</script>
<div class="time">
<div id="date"></div>
<div id="now"></div>
<div id="day"></div>
</div>
<div class="hour-hand" id="h"></div>
<div class="minute-hand" id="m"></div>
<div class="second-hand" id="s"></div>
<div class="center"></div>
</div>
<script>
let f = (e, i) => (i != 0 && e < 10 ? '0' + e : e);
setInterval(() => {
let t = new Date();
rotateElement(h, t.getHours() * 30 + t.getMinutes() / 60 * 30);
rotateElement(m, t.getMinutes() * 6 + t.getSeconds() / 60 * 6);
rotateElement(s, t.getSeconds() * 6 + t.getMilliseconds() / 1000 * 6);
date.innerHTML = [t.getFullYear(), t.getMonth() + 1, t.getDate()].map(f).join('-');
day.innerHTML = '星期' + '日一二三四五六' [t.getDay()];
now.innerHTML = [t.getHours(), t.getMinutes(), t.getSeconds()].map(f).join(':');
}, 1000 / 60);
</script>
</body>
</html>
\ No newline at end of file
</html>
......@@ -23,7 +23,7 @@ func main() {
cefApp := cef.NewApplication()
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "http://localhost:22022/index.html"
if common.IsLinux() {
if common.IsLinux() && cefApp.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......
......@@ -28,7 +28,7 @@ func main() {
cefApp := cef.NewApplication()
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "https://energy.yanghy.cn"
if common.IsLinux() {
if common.IsLinux() && cefApp.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......
......@@ -27,12 +27,13 @@ func main() {
loadEnergyUrl consts.MenuId
loadBaiduUrl consts.MenuId
)
event.SetOnBeforeContextMenu(func(sender lcl.IObject, browser *cef.ICefBrowser, frame *cef.ICefFrame, params *cef.ICefContextMenuParams, model *cef.ICefMenuModel) {
event.SetOnBeforeContextMenu(func(sender lcl.IObject, browser *cef.ICefBrowser, frame *cef.ICefFrame, params *cef.ICefContextMenuParams, model *cef.ICefMenuModel) bool {
model.AddSeparator()
loadEnergyUrl = model.CefMis.NextCommandId()
model.AddCheckItem(loadEnergyUrl, "load-energy")
loadBaiduUrl = model.CefMis.NextCommandId()
model.AddCheckItem(loadBaiduUrl, "load-baidu")
return false
})
event.SetOnContextMenuCommand(func(sender lcl.IObject, browser *cef.ICefBrowser, frame *cef.ICefFrame, params *cef.ICefContextMenuParams, commandId consts.MenuId, eventFlags uint32, result *bool) {
if commandId == loadEnergyUrl {
......
......@@ -28,7 +28,7 @@ func main() {
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "http://localhost:22022/response-filter.html"
cef.BrowserWindow.Config.Title = "Energy - response-filter"
if common.IsLinux() {
if common.IsLinux() && app.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......
......@@ -26,7 +26,7 @@ func main() {
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "https://www.baidu.com/"
cef.BrowserWindow.Config.Title = "Energy - Scheme"
if common.IsLinux() {
if common.IsLinux() && cefApp.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......@@ -40,7 +40,7 @@ func main() {
var idClear consts.MenuId
var idURL consts.MenuId
// 在右键菜单实现这个示例
event.SetOnBeforeContextMenu(func(sender lcl.IObject, browser *cef.ICefBrowser, frame *cef.ICefFrame, params *cef.ICefContextMenuParams, model *cef.ICefMenuModel) {
event.SetOnBeforeContextMenu(func(sender lcl.IObject, browser *cef.ICefBrowser, frame *cef.ICefFrame, params *cef.ICefContextMenuParams, model *cef.ICefMenuModel) bool {
model.AddSeparator()
idScheme = model.CefMis.NextCommandId()
model.AddItem(idScheme, "RegScheme")
......@@ -48,6 +48,7 @@ func main() {
model.AddItem(idClear, "ClearScheme")
idURL = model.CefMis.NextCommandId()
model.AddItem(idURL, "URL")
return true
})
// 右键菜单命令
event.SetOnContextMenuCommand(func(sender lcl.IObject, browser *cef.ICefBrowser, frame *cef.ICefFrame, params *cef.ICefContextMenuParams, commandId consts.MenuId, eventFlags uint32, result *bool) {
......
package main
import (
"fmt"
"github.com/energye/energy/v2/cef"
)
func main() {
//全局初始化 每个应用都必须调用的
cef.GlobalInit(nil, nil)
//创建应用
app := cef.NewApplication()
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "https://energy.yanghy.cn"
cef.BrowserWindow.SetBrowserInit(func(event *cef.BrowserEvent, window cef.IBrowserWindow) {
screen := window.Screen()
pr := screen.Primary()
fmt.Println("Primary:", pr)
fmt.Println("MonitorCount", screen.Count())
for i := 0; i < screen.Count(); i++ {
monitor := screen.Get(i)
fmt.Println("\tmonitor", i, "work-rect:", monitor)
}
})
//运行应用
cef.Run(app)
}
......@@ -22,7 +22,7 @@ func main() {
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "http://localhost:22022/index.html"
cef.BrowserWindow.Config.Title = "Energy 搜索页面中文本"
if common.IsLinux() {
if common.IsLinux() && cefApp.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......
......@@ -47,9 +47,9 @@ func main() {
//子进程执行程序如果在 chromium 目录中可不配置
var subExePath string
if common.IsWindows() {
subExePath = path.Join(wd, "example", "sub-process", "sub-process", "sub-process.exe")
subExePath = path.Join(wd, "sub-process.exe")
} else if common.IsLinux() {
subExePath = path.Join(wd, "example", "sub-process", "sub-process", "sub-process")
subExePath = path.Join(wd, "sub-process")
} else if common.IsDarwin() {
//MacOS SetBrowseSubprocessPath 将不起任何作用。
//独立的子程序包需要在 macapp.MacApp.SetBrowseSubprocessPath 配置
......@@ -61,7 +61,7 @@ func main() {
//cefApp.SetSingleProcess(false) //单进程 或 多进程 ,单进程上面的子进程配置就不起作用了
cefApp.SetBrowserSubprocessPath(subExePath)
//主进程初始化
src.MainBrowserInit()
src.MainBrowserInit(cefApp)
cef.SetBrowserProcessStartAfterCallback(func(b bool) {
fmt.Println("主进程启动 创建一个内置http服务")
//通过内置http服务加载资源
......
......@@ -8,11 +8,11 @@ import (
)
//主进程浏览器初始化
func MainBrowserInit() {
func MainBrowserInit(app *cef.TCEFApplication) {
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "http://localhost:22022/index.html"
cef.BrowserWindow.Config.Title = "ENERGY 区分主/子进程执行文件"
if common.IsLinux() {
if common.IsLinux() && app.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......
......@@ -38,7 +38,7 @@ func main() {
cef.BrowserWindow.Config.Url = "http://localhost:22022/sysdialog.html"
}
cef.BrowserWindow.Config.Title = "Energy - dialog"
if common.IsLinux() {
if common.IsLinux() && app.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......
......@@ -28,7 +28,7 @@ func main() {
cefApp := cef.NewApplication()
//指定一个URL地址,或本地html文件目录
cef.BrowserWindow.Config.Url = "http://localhost:22022/webkit-register.html"
if common.IsLinux() {
if common.IsLinux() && cefApp.IsUIGtk3() {
cef.BrowserWindow.Config.IconFS = "resources/icon.png"
} else {
cef.BrowserWindow.Config.IconFS = "resources/icon.ico"
......
//----------------------------------------
//
// 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 (
"fmt"
"github.com/energye/energy/v2/cef"
"github.com/energye/energy/v2/consts"
"github.com/energye/energy/v2/consts/messages"
"github.com/energye/golcl/lcl"
"github.com/energye/golcl/lcl/api"
"github.com/energye/golcl/lcl/rtl"
"github.com/energye/golcl/lcl/types"
"github.com/energye/golcl/lcl/types/colors"
)
type MainWindowDemo struct {
*lcl.TForm
}
//自定义浏览器创建
//示例演示将CEF做为一个LCL组件使用
//在适当的情况动态创建一个或多个浏览器,实际可做为子组件使用或弹出窗口,根据需求而定
//需要自己正确处理关闭流程
//可以自己定制出CEF的使用
func main() {
cef.GlobalInit(nil, nil)
defer func() {
api.EnergyLibRelease()
}()
//创建应用
app := cef.NewApplication()
// 启动主进程
success := app.StartMainProcess()
if success {
// 创建窗口并运行应用
var window = &MainWindowDemo{}
lcl.RunApp(&window)
}
}
func (m *MainWindowDemo) OnFormCreate(sender lcl.IObject) {
fmt.Println("MainWindowDemo OnFormCreate")
m.SetCaption("主窗口")
m.SetWidth(1000)
m.SetHeight(900)
m.ScreenCenter()
// 普通Panel
panel := lcl.NewPanel(m)
panel.SetParent(m)
panel.SetWidth(m.Width())
panel.SetHeight(800)
panel.SetTop(100)
panel.SetColor(colors.ClCyan)
panel.SetAnchors(types.NewSet(types.AkTop, types.AkRight, types.AkBottom, types.AkLeft))
labTxt := lcl.NewLabel(m)
labTxt.SetParent(panel)
labTxt.SetCaption("普通Panel") //标识一下确定是没有浏览器的panel
// 带有浏览器的panel
browserPanel := lcl.NewPanel(m)
browserPanel.SetParent(m)
browserPanel.SetWidth(m.Width())
browserPanel.SetHeight(800)
browserPanel.SetTop(100)
browserPanel.SetVisible(false)
browserPanel.SetAnchors(types.NewSet(types.AkTop, types.AkRight, types.AkBottom, types.AkLeft))
// 普通Panel 按钮
panelBtn := lcl.NewButton(m)
panelBtn.SetParent(m)
panelBtn.SetCaption("显示普通Panel")
panelBtn.SetWidth(200)
panelBtn.SetOnClick(func(sender lcl.IObject) {
panel.SetVisible(true)
browserPanel.SetVisible(false)
})
// 显示浏览器Panel 按钮
browserPanelBtn := lcl.NewButton(m)
browserPanelBtn.SetParent(m)
browserPanelBtn.SetCaption("显示浏览器Panel")
browserPanelBtn.SetWidth(200)
browserPanelBtn.SetLeft(250)
//在按钮事件中创建浏览器,并设置到指定的panel中
//需要注意的是,浏览器有一个正确的关闭流程。
//在窗口的关闭事件中 close, closeQuery
var chromiumBrowser cef.ICEFChromiumBrowser
//窗口关闭流程标识
var (
canClose bool
isClosing bool
)
browserPanelBtn.SetOnClick(func(sender lcl.IObject) {
panel.SetVisible(false)
browserPanel.SetVisible(true)
if chromiumBrowser == nil {
chromiumBrowser = cef.NewChromiumBrowser(browserPanel, nil)
chromiumBrowser.Chromium().SetEnableMultiBrowserMode(true)
chromiumBrowser.Chromium().SetDefaultURL("https://www.baidu.com")
//windowParent
chromiumBrowser.WindowParent().DefaultAnchors()
chromiumBrowser.WindowParent().SetOnEnter(func(sender lcl.IObject) {
chromiumBrowser.Chromium().Initialized()
chromiumBrowser.Chromium().FrameIsFocused()
chromiumBrowser.Chromium().SetFocus(true)
})
chromiumBrowser.WindowParent().SetOnExit(func(sender lcl.IObject) {
chromiumBrowser.Chromium().SendCaptureLostEvent()
})
//禁用右键菜单
chromiumBrowser.Chromium().SetOnBeforeContextMenu(func(sender lcl.IObject, browser *cef.ICefBrowser, frame *cef.ICefFrame, params *cef.ICefContextMenuParams, model *cef.ICefMenuModel) {
model.Clear()
})
//禁止弹出新窗口
chromiumBrowser.Chromium().SetOnOpenUrlFromTab(func(sender lcl.IObject, browser *cef.ICefBrowser, frame *cef.ICefFrame, targetUrl string, targetDisposition consts.TCefWindowOpenDisposition, userGesture bool) bool {
fmt.Println("OnOpenUrlFromTab")
return true
})
//禁止弹出新窗口
chromiumBrowser.Chromium().SetOnBeforePopup(func(sender lcl.IObject, browser *cef.ICefBrowser, frame *cef.ICefFrame, beforePopupInfo *cef.BeforePopupInfo, client *cef.ICefClient, noJavascriptAccess *bool) bool {
fmt.Println("OnBeforePopup")
return true
})
// 以下是窗口关闭时 正确关闭浏览器的流程
// windows的关闭示例
chromiumBrowser.Chromium().SetOnClose(func(sender lcl.IObject, browser *cef.ICefBrowser, aAction *consts.TCefCloseBrowserAction) {
*aAction = consts.CbaDelay
cef.QueueAsyncCall(func(id int) { //run in main thread
chromiumBrowser.WindowParent().Free()
})
})
chromiumBrowser.Chromium().SetOnBeforeClose(func(sender lcl.IObject, browser *cef.ICefBrowser) {
canClose = true // 允许关闭窗口
cef.QueueAsyncCall(func(id int) { // main thread run
rtl.PostMessage(m.Handle(), messages.WM_CLOSE, 0, 0) //发送关闭消息
})
})
}
})
// 以下是窗口关闭时 正确关闭浏览器的流程
// windows的关闭示例
m.SetOnClose(func(sender lcl.IObject, action *types.TCloseAction) {
*action = types.CaFree
})
m.SetOnCloseQuery(func(sender lcl.IObject, close *bool) {
*close = canClose // 是否允许关闭窗口标识
cef.QueueAsyncCall(func(id int) {
if !isClosing {
isClosing = true
if chromiumBrowser != nil {
chromiumBrowser.Chromium().CloseBrowser(true) // 关闭浏览器
}
m.Hide()
}
})
})
}
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
package types
type TRect struct {
Left int32
Top int32
Right int32
Bottom int32
}
type WindowPos struct {
Hwnd THandle
HwndInsertAfter THandle
X Integer
Y Integer
Cx Integer
Cy Integer
Flags Cardinal
}
type Paint struct {
Hdc HDC
FErase BOOL
RcPaint TRect
FRestore BOOL
FIncUpdate BOOL
RgbReserved [32]uint8
}
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
//go:build 386
package types
type TPaint struct {
Msg Cardinal
DC HDC
PaintStruct Paint
Result LResult
}
type TMove struct {
Msg Cardinal
MoveType PtrInt // 0 = update, 1 = force RequestAlign, 128 = Source is Interface (Widget has moved)
Dummy LPARAM // needed for64 bit alignment
Result LResult
}
type TSize struct {
Msg Cardinal
SizeType PtrInt // see LCLType.pp (e.g. Size_Restored)
Width Word
Height Word
Result LResult
}
type TWindowPosChanged struct {
Msg Cardinal
Unused WPARAM
WindowPos WindowPos
Result LPARAM
}
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
//go:build amd64 || arm64
package types
type TDWordFiller struct {
Filler [4]uint8
}
type TPaint struct {
Msg Cardinal
_UnusedMsg Cardinal
DC HDC
PaintStruct Paint
Result LResult
}
type TMove struct {
Msg Cardinal
_UnusedMsg Cardinal
MoveType PtrInt // 0 = update, 1 = force RequestAlign, 128 = Source is Interface (Widget has moved)
Dummy LPARAM // needed for64 bit alignment
Result LResult
}
type TSize struct {
Msg Cardinal
MsgFiller TDWordFiller
SizeType PtrInt // see LCLType.pp (e.g. Size_Restored)
Width Word
Height Word
LParamfiller TDWordFiller
Result LResult
}
type TWindowPosChanged struct {
Msg Cardinal
_UnusedMsg Cardinal
Unused WPARAM
WindowPos WindowPos
Result LPARAM
}