From 58a23467bf6b49e7a7398c1c2175048af0021672 Mon Sep 17 00:00:00 2001 From: yanghy Date: Thu, 20 Jul 2023 19:52:58 +0800 Subject: [PATCH] A: TForm WM Message --- cef/application-run.go | 10 +- cef/browser-window-drag_linux.go | 163 +++++++++++++++++- cef/browser-window-lcl.go | 47 +++++ cef/internal/def/proc-def-index.go | 5 +- cef/internal/def/proc-def.go | 5 +- .../custom-drag-window/custom-drag-window.go | 10 ++ example/frameless/frameless.go | 2 +- types/types.go | 32 ++++ 8 files changed, 256 insertions(+), 18 deletions(-) diff --git a/cef/application-run.go b/cef/application-run.go index fcd652df..1e2c3d00 100644 --- a/cef/application-run.go +++ b/cef/application-run.go @@ -67,10 +67,8 @@ func Run(app *TCEFApplication) { // 启动主进程 success := app.StartMainProcess() if success { - if app.IsUIGtk3() { - //LCL -> Linux 必须在主进程启动之后初始化组件 - lclwidget.CustomWidgetSetInitialization() - } + //LCL -> Linux 必须在主进程启动之后初始化组件 + lclwidget.CustomWidgetSetInitialization() // 主进程启动成功之后回调 if browserProcessStartAfterCallback != nil { browserProcessStartAfterCallback(success) @@ -87,9 +85,7 @@ func Run(app *TCEFApplication) { } // LCL窗口 lcl.RunApp(&BrowserWindow.mainBrowserWindow) - if app.IsUIGtk3() { - lclwidget.CustomWidgetSetFinalization() - } + lclwidget.CustomWidgetSetFinalization() } } } diff --git a/cef/browser-window-drag_linux.go b/cef/browser-window-drag_linux.go index 2ed97a86..59a1b045 100644 --- a/cef/browser-window-drag_linux.go +++ b/cef/browser-window-drag_linux.go @@ -12,20 +12,175 @@ 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) { - + // MacOS只在LCL窗口中使用自定义窗口拖拽, VF窗口默认已实现 + // 在MacOS中LCL窗口没有有效的消息事件 + var executeJS = ` +energyExtension.drag.setEnableDrag(` + strconv.FormatBool(application.EnableWebkitAppRegion()) + `); +energyExtension.drag.setup();` + frame.ExecuteJavaScript(executeJS, "", 0) } // 窗口拖拽JS扩展处理器 // 1. 注册JS扩展到CEF, 注册鼠标事件,通过本地函数在Go里处理鼠标事件 // 2. 通过IPC将鼠标消息发送到主进程,主进程监听到消息处理鼠标事件 -// 3. linux 默认使用VF窗口组件, 所以不需要使用该实现 +// 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 { + 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) + } + } } diff --git a/cef/browser-window-lcl.go b/cef/browser-window-lcl.go index f43f5707..1176114d 100644 --- a/cef/browser-window-lcl.go +++ b/cef/browser-window-lcl.go @@ -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,6 +31,7 @@ import ( "github.com/energye/golcl/lcl/types" "runtime" "time" + "unsafe" ) // LCLBrowserWindow 基于CEF lcl 窗口组件 @@ -1027,3 +1031,46 @@ func (m *LCLBrowserWindow) registerDefaultChromiumCloseEvent() { } }) } + +type messageType int32 + +const ( + mtMove messageType = iota + 1 + mtSize + mtWindowPosChanged +) + +type wmMove func(message *t.TMove) +type wmSize func(message *t.TSize) +type wmWindowPosChanged func(message *t.TWindowPosChanged) + +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 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 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 + }) +} diff --git a/cef/internal/def/proc-def-index.go b/cef/internal/def/proc-def-index.go index 94153f62..6c02c336 100644 --- a/cef/internal/def/proc-def-index.go +++ b/cef/internal/def/proc-def-index.go @@ -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 diff --git a/cef/internal/def/proc-def.go b/cef/internal/def/proc-def.go index e574a094..26f64aca 100644 --- a/cef/internal/def/proc-def.go +++ b/cef/internal/def/proc-def.go @@ -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), diff --git a/example/custom-drag-window/custom-drag-window.go b/example/custom-drag-window/custom-drag-window.go index 09d424f3..4e562261 100644 --- a/example/custom-drag-window/custom-drag-window.go +++ b/example/custom-drag-window/custom-drag-window.go @@ -6,6 +6,7 @@ import ( "github.com/energye/energy/v2/cef" "github.com/energye/energy/v2/common" "github.com/energye/energy/v2/pkgs/assetserve" + "github.com/energye/energy/v2/types" ) //go:embed resources @@ -30,5 +31,14 @@ func main() { server.Assets = &resources go server.StartHttpServer() }) + cef.BrowserWindow.SetBrowserInit(func(event *cef.BrowserEvent, window cef.IBrowserWindow) { + bw := window.AsLCLBrowserWindow().BrowserWindow() + bw.SetOnWMSize(func(message *types.TSize) { + fmt.Println("SetOnWMSize", message) + }) + bw.SetOnWMMove(func(message *types.TMove) { + fmt.Println("SetOnWMMove", message) + }) + }) cef.Run(app) } diff --git a/example/frameless/frameless.go b/example/frameless/frameless.go index b822bf15..c495ee01 100644 --- a/example/frameless/frameless.go +++ b/example/frameless/frameless.go @@ -44,7 +44,7 @@ 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 diff --git a/types/types.go b/types/types.go index 7c2572d7..740746e9 100644 --- a/types/types.go +++ b/types/types.go @@ -412,3 +412,35 @@ func (m *HRGN) Free() { func (m *HRGN) Instance() uintptr { return uintptr(m.instance) } + +type WindowPos struct { + Hwnd HWND + HwndInsertAfter HWND + X Integer + Y Integer + Cx Integer + Cy Integer + Flags UINT +} + +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 +}