This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch main
in repository ego.

View the commit online.

commit 3bb76f28bf1b87d6392e91523c28f6fc8f27080a
Author: [email protected] <[email protected]>
AuthorDate: Mon Mar 30 22:06:37 2026 -0600

    feat(ego-gen): generate callback trampolines and closure-accepting methods
    
    Generate per-typedef //export trampolines for EFL function pointer
    callbacks, plus Go methods that accept closures and bridge them
    to C via the CallbackRegister/free_cb pattern. Unlocks signal
    callbacks, thread IO, and filter model methods.
    
    Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
---
 cmd/ego-gen/generator.go                           |  45 +++++++++
 cmd/ego-gen/main.go                                | 109 +++++++++++++++++----
 cmd/ego-gen/templates/callback_trampolines.go.tmpl |  75 ++++++++++++++
 cmd/ego-gen/templates/class.go.tmpl                |  46 ++++++++-
 efl/callback_trampolines_gen.go                    |  95 ++++++++++++++++++
 efl/canvas/layout.go                               |  23 +++++
 efl/eo/appthread.go                                |  16 +++
 efl/eo/filter_model.go                             |   9 ++
 efl/eo/thread.go                                   |  16 +++
 efl/eo/thread_io.go                                |  16 +++
 efl/layout/signal.go                               |  23 +++++
 efl/ui/image.go                                    |  23 +++++
 efl/ui/layout_base.go                              |  23 +++++
 13 files changed, 501 insertions(+), 18 deletions(-)

diff --git a/cmd/ego-gen/generator.go b/cmd/ego-gen/generator.go
index 0b0c37d..610645b 100644
--- a/cmd/ego-gen/generator.go
+++ b/cmd/ego-gen/generator.go
@@ -221,6 +221,14 @@ type EventData struct {
 	PayloadCType  string
 }
 
+// PackageCallbackData holds all unique callback typedefs for a single generated
+// package. It is used to render the per-package callback_trampolines_gen.go file
+// that contains the //export trampoline functions.
+type PackageCallbackData struct {
+	PackageName   string
+	CallbackTypes []CallbackTypeData
+}
+
 // EnumData holds the information needed to render a Go file for one EFL enum.
 type EnumData struct {
 	PackageName string
@@ -283,6 +291,43 @@ func (g *Generator) GenerateEnum(data EnumData) error {
 	return g.generate("enum.go.tmpl", data.PackageName, toSnake(data.GoTypeName), data)
 }
 
+// GenerateCallbackTrampolines renders the callback trampolines template and
+// writes the result to outputDir/callback_trampolines_gen.go (in the root
+// output package). The generated file contains //export functions and must not
+// be in a file that also defines cgo preamble C code (CGO //export constraint).
+// All trampolines go into one file so that //export symbols are defined exactly
+// once across the entire binary (duplicate-symbol linker errors would otherwise
+// occur when multiple sub-packages forward the same mixin callback type).
+func (g *Generator) GenerateCallbackTrampolines(data PackageCallbackData) error {
+	// Write directly into g.outputDir (the base efl package), not a subdirectory.
+	return g.generateInDir("callback_trampolines.go.tmpl", g.outputDir, "callback_trampolines_gen", data)
+}
+
+// generateInDir is like generate but writes to an explicit directory instead of
+// computing it from outputDir + pkg.
+func (g *Generator) generateInDir(tmplName, dir, baseName string, data any) error {
+	if err := os.MkdirAll(dir, 0o755); err != nil {
+		return fmt.Errorf("generator: mkdir %s: %w", dir, err)
+	}
+
+	var buf bytes.Buffer
+	if err := g.tmpl.ExecuteTemplate(&buf, tmplName, data); err != nil {
+		return fmt.Errorf("generator: execute template %s: %w", tmplName, err)
+	}
+
+	src := buf.Bytes()
+	formatted, err := format.Source(src)
+	if err != nil {
+		formatted = src
+	}
+
+	outPath := filepath.Join(dir, baseName+".go")
+	if err := os.WriteFile(outPath, formatted, 0o644); err != nil {
+		return fmt.Errorf("generator: write %s: %w", outPath, err)
+	}
+	return nil
+}
+
 // generate executes the named template with the given data, formats the
 // output with go/format, and writes it to outputDir/pkg/filename.go.
 // If go/format fails, the raw output is written so the file can be inspected.
diff --git a/cmd/ego-gen/main.go b/cmd/ego-gen/main.go
index 2d332ea..42d9761 100644
--- a/cmd/ego-gen/main.go
+++ b/cmd/ego-gen/main.go
@@ -36,9 +36,7 @@ var methodBlocklist = map[string]bool{
 	// efl.Layout.Calc — return struct by value; cannot be converted to unsafe.Pointer by cgo
 	"efl_layout_calc_size_min":      true,
 	"efl_layout_calc_parts_extends": true,
-	// efl.Layout.Signal — function has more params than Eolian reports
-	"efl_layout_signal_callback_add": true,
-	"efl_layout_signal_callback_del": true,
+	// efl.Layout.Signal — callback params handled via callback trampoline generation.
 	// efl.Layout.Signal — takes const Eina_Value by value; struct-valued parameter
 	"efl_layout_signal_message_send": true,
 	// efl.Access.Text — character_extents_get and range_extents_get take an extra Eina_Rect* out-param
@@ -60,8 +58,7 @@ var methodBlocklist = map[string]bool{
 	"efl_file_mmap_set": true,
 	// efl.File_Save — struct-by-value parameter incompatible with generated pointer wrapper
 	"efl_file_save": true,
-	// efl.Filter_Model — callback parameter not reported by Eolian; wrong argument count
-	"efl_filter_model_filter_set": true,
+	// efl.Filter_Model — callback param handled via callback trampoline generation.
 	// efl.Object — struct-by-pointer mismatch in event forwarder methods
 	"efl_event_callback_forwarder_priority_add": true,
 	"efl_event_callback_forwarder_del":          true,
@@ -70,9 +67,7 @@ var methodBlocklist = map[string]bool{
 	// efl.Text_Formatter — wrong argument count reported by Eolian
 	"efl_text_formatter_attribute_insert": true,
 	"efl_text_formatter_attribute_clear":  true,
-	// efl.ThreadIO — callback struct parameters with extra data args not reported by Eolian
-	"efl_threadio_call":      true,
-	"efl_threadio_call_sync": true,
+	// efl.ThreadIO — callback params handled via callback trampoline generation.
 	// efl.Input.Pointer — position setters now handled via known struct support.
 	// efl.Text_Cursor.Object — returns Eina_Rect by value (struct return not supported in indexed property)
 	"efl_text_cursor_object_lower_cursor_geometry_get": true,
@@ -162,7 +157,9 @@ var methodBlocklist = map[string]bool{
 	// efl.Net.Socket.Udp — more methods returning Eina_Error
 	"efl_net_socket_udp_multicast_join":   true,
 	"efl_net_socket_udp_multicast_leave":  true,
-	// efl.Ui.Format — func_set takes callback+data+free_cb (3 extra params, not 1)
+	// efl.Ui.Format — func_set is a property setter that takes callback+data+free_cb
+	// (3 extra params not reflected in Eolian's property model). Keep blocked to prevent
+	// the property wrapper from generating a broken C shim with too few arguments.
 	"efl_ui_format_func_set": true,
 	// efl.Ui.Dnd — struct-by-value Eina_Content parameter
 	"efl_ui_dnd_drag_start": true,
@@ -180,9 +177,11 @@ var methodBlocklist = map[string]bool{
 	"efl_ui_property_bind": true,
 	// efl.Ui.Selection — struct-by-value Eina_Content parameter
 	"efl_ui_selection_set": true,
-	// efl.Ui.ViewModel — returns Eina_Error; callback-style with extra params
+	// efl.Ui.ViewModel — returns Eina_Error; cannot be wrapped
 	"efl_ui_view_model_property_bind":      true,
 	"efl_ui_view_model_factory_bind":       true,
+	// efl.Ui.ViewModel — property_logic_add has complex multi-callback + iterator params
+	// that the generator cannot handle (Eolian reports fewer params than the C declaration).
 	"efl_ui_view_model_property_logic_add": true,
 	"efl_ui_view_model_property_logic_del": true,
 	// efl.Ui.ViewModel — more methods returning Eina_Error
@@ -331,6 +330,10 @@ func run(eoDirs, outputDir, templateDir string, useSystem bool) error {
 	// struct-typed properties from parent interfaces.
 	pkgOptionNames := make(map[string]map[string]bool)
 
+	// pkgCallbackTypes accumulates unique callback typedefs per package for the
+	// second-pass trampoline file generation.
+	pkgCallbackTypes := make(map[string]map[string]CallbackTypeData)
+
 	for _, c := range classes {
 		data, err := buildClassData(c, pkgOptionNames)
 		if err != nil {
@@ -345,9 +348,47 @@ func run(eoDirs, outputDir, templateDir string, useSystem bool) error {
 			continue
 		}
 		generated++
+
+		// Accumulate callback types for this package.
+		if len(data.CallbackTypes) > 0 {
+			if pkgCallbackTypes[data.PackageName] == nil {
+				pkgCallbackTypes[data.PackageName] = make(map[string]CallbackTypeData)
+			}
+			for _, ct := range data.CallbackTypes {
+				pkgCallbackTypes[data.PackageName][ct.EolianName] = ct
+			}
+		}
 	}
 
-	// Step 7: Log statistics.
+	// Step 7: Generate a single callback trampolines file in the base "efl" package.
+	// All //export trampoline functions must be defined exactly once across the
+	// entire binary; placing them in the base package avoids duplicate-symbol
+	// linker errors when multiple sub-packages forward the same mixin callback.
+	allCallbackTypeMap := make(map[string]CallbackTypeData)
+	for _, typeMap := range pkgCallbackTypes {
+		for name, ct := range typeMap {
+			allCallbackTypeMap[name] = ct
+		}
+	}
+	if len(allCallbackTypeMap) > 0 {
+		var allTypes []CallbackTypeData
+		for _, ct := range allCallbackTypeMap {
+			allTypes = append(allTypes, ct)
+		}
+		sort.Slice(allTypes, func(i, j int) bool {
+			return allTypes[i].EolianName < allTypes[j].EolianName
+		})
+		cbData := PackageCallbackData{
+			PackageName:   "efl",
+			CallbackTypes: allTypes,
+		}
+		if err := gen.GenerateCallbackTrampolines(cbData); err != nil {
+			log.Printf("ego-gen: generate callback trampolines: %v", err)
+			errCount++
+		}
+	}
+
+	// Step 8: Log statistics.
 	log.Printf("ego-gen: generated=%d skipped=%d errors=%d", generated, skipped, errCount)
 
 	if errCount > 0 {
@@ -832,6 +873,22 @@ func buildClassData(c *Class, pkgOptionNames map[string]map[string]bool) (ClassD
 		}
 	}
 
+	// Collect unique callback types for trampoline generation.
+	callbackTypeMap := make(map[string]CallbackTypeData)
+	for _, m := range methods {
+		for _, cp := range m.CallbackParams {
+			callbackTypeMap[cp.CallbackType.EolianName] = *cp.CallbackType
+		}
+	}
+	var callbackTypes []CallbackTypeData
+	for _, ct := range callbackTypeMap {
+		callbackTypes = append(callbackTypes, ct)
+	}
+	// Sort for deterministic output.
+	sort.Slice(callbackTypes, func(i, j int) bool {
+		return callbackTypes[i].EolianName < callbackTypes[j].EolianName
+	})
+
 	return ClassData{
 		PackageName:    pkgName,
 		GoName:         goName,
@@ -857,6 +914,8 @@ func buildClassData(c *Class, pkgOptionNames map[string]map[string]bool) (ClassD
 		HasIterators:        len(iteratorMethods) > 0,
 		IteratorStructTypes: deduplicateIteratorStructTypes(iteratorMethods),
 		GlobalFunctions:     globalFunctions,
+		CallbackTypes:       callbackTypes,
+		HasCallbacks:        len(callbackTypes) > 0,
 	}, nil
 }
 
@@ -1105,7 +1164,22 @@ func buildMethodData(f *Function, cPrefix string) MethodData {
 
 	var params []ParamData
 	var outParams []OutParamData
+	var callbackParams []CallbackParamData
 	for _, p := range f.Parameters() {
+		// Check for callback function pointer parameter.
+		if p.Direction() == ParamIn && isCallbackParam(p) {
+			cbd, err := buildCallbackTypeData(p)
+			if err != nil {
+				log.Printf("ego-gen: skip callback param %s in %s: %v", p.Name(), methodName, err)
+				continue
+			}
+			callbackParams = append(callbackParams, CallbackParamData{
+				GoName:       snakeToLowerCamel(p.Name()),
+				CallbackType: cbd,
+			})
+			continue
+		}
+
 		if p.Direction() != ParamIn {
 			if p.Direction() == ParamOut || p.Direction() == ParamInOut {
 				pt := p.Type()
@@ -1141,12 +1215,13 @@ func buildMethodData(f *Function, cPrefix string) MethodData {
 	}
 
 	return MethodData{
-		GoName:      goName,
-		CName:       cName,
-		Params:      params,
-		ReturnType:  returnType,
-		ReturnCType: returnCType,
-		OutParams:   outParams,
+		GoName:         goName,
+		CName:          cName,
+		Params:         params,
+		ReturnType:     returnType,
+		ReturnCType:    returnCType,
+		OutParams:      outParams,
+		CallbackParams: callbackParams,
 	}
 }
 
diff --git a/cmd/ego-gen/templates/callback_trampolines.go.tmpl b/cmd/ego-gen/templates/callback_trampolines.go.tmpl
new file mode 100644
index 0000000..0c080c6
--- /dev/null
+++ b/cmd/ego-gen/templates/callback_trampolines.go.tmpl
@@ -0,0 +1,75 @@
+// Code generated by ego-gen. DO NOT EDIT.
+
+package {{.PackageName}}
+
+/*
+#cgo pkg-config: elementary
+#define EFL_BETA_API_SUPPORT 1
+// Define all EFL_*_PROTECTED macros to expose @protected methods.
+#define EFL_ACCESS_ACTION_PROTECTED 1
+#define EFL_ACCESS_COMPONENT_PROTECTED 1
+#define EFL_ACCESS_EDITABLE_TEXT_PROTECTED 1
+#define EFL_ACCESS_OBJECT_PROTECTED 1
+#define EFL_ACCESS_SELECTION_PROTECTED 1
+#define EFL_ACCESS_TEXT_PROTECTED 1
+#define EFL_ACCESS_VALUE_PROTECTED 1
+#define EFL_ACCESS_WIDGET_ACTION_PROTECTED 1
+#define EFL_CONFIG_GLOBAL_PROTECTED 1
+#define EFL_GFX_HINT_PROTECTED 1
+#define EFL_IO_CLOSER_FD_PROTECTED 1
+#define EFL_IO_COPIER_PROTECTED 1
+#define EFL_IO_POSITIONER_FD_PROTECTED 1
+#define EFL_IO_READER_FD_PROTECTED 1
+#define EFL_IO_READER_PROTECTED 1
+#define EFL_IO_SIZER_FD_PROTECTED 1
+#define EFL_IO_WRITER_FD_PROTECTED 1
+#define EFL_IO_WRITER_PROTECTED 1
+#define EFL_LAYOUT_CALC_PROTECTED 1
+#define EFL_LOOP_PROTECTED 1
+#define EFL_PACK_LAYOUT_PROTECTED 1
+#define EFL_PART_PROTECTED 1
+#define EFL_UI_FACTORY_PROTECTED 1
+#define EFL_UI_FOCUS_COMPOSITION_PROTECTED 1
+#define EFL_UI_FOCUS_LAYER_PROTECTED 1
+#define EFL_UI_FOCUS_OBJECT_PROTECTED 1
+#define EFL_UI_FORMAT_PROTECTED 1
+#define EFL_UI_L10N_PROTECTED 1
+#define EFL_UI_SCROLLBAR_PROTECTED 1
+#define EFL_UI_SCROLL_MANAGER_PROTECTED 1
+#define EFL_UI_WIDGET_FOCUS_MANAGER_PROTECTED 1
+#define EFL_UI_WIDGET_PROTECTED 1
+#define EFL_UI_WIDGET_SCROLLABLE_CONTENT_PROTECTED 1
+#define EFL_CANVAS_GESTURE_PROTECTED 1
+#define EFL_CANVAS_GESTURE_CUSTOM_PROTECTED 1
+#define EFL_CANVAS_GROUP_PROTECTED 1
+#define EFL_CANVAS_OBJECT_PROTECTED 1
+#define EFL_INPUT_CLICKABLE_PROTECTED 1
+#include <Efl_Ui.h>
+*/
+import "C"
+
+import "unsafe"
+
+// Ensure unused imports are not flagged.
+var _ = unsafe.Pointer(nil)
+
+//export egoCallbackFree
+func egoCallbackFree(data unsafe.Pointer) {
+    CallbackRemove(uintptr(data))
+}
+
+{{- range .CallbackTypes}}
+
+//export {{.GoTrampolineName}}
+func {{.GoTrampolineName}}(data unsafe.Pointer{{range .Params}}, {{.GoName}} {{if .IsEo}}*C.Eo{{else if needsStringConversion .CType}}*C.char{{else if isBoolType .CType}}C.{{cTypeToCgo .CType}}{{else if isPointerType .GoType}}unsafe.Pointer{{else}}C.{{cTypeToCgo .CType}}{{end}}{{end}}) {{if .ReturnCType}}C.{{cTypeToCgo .ReturnCType}}{{end}} {
+    fn := CallbackLookup[{{.GoFuncType}}](uintptr(data))
+    if fn == nil {
+{{- if .ReturnCType}}
+        var _zero C.{{cTypeToCgo .ReturnCType}}
+        return _zero
+{{- end}}
+        return
+    }
+    {{if .ReturnCType}}_ = {{end}}fn({{range $i, $p := .Params}}{{if $i}}, {{end}}{{if $p.IsEo}}unsafe.Pointer({{$p.GoName}}){{else if needsStringConversion $p.CType}}C.GoString({{$p.GoName}}){{else if isBoolType $p.CType}}{{$p.GoName}} != 0{{else if isPointerType $p.GoType}}{{$p.GoName}}{{else}}{{$p.GoType}}({{$p.GoName}}){{end}}{{end}})
+}
+{{- end}}
diff --git a/cmd/ego-gen/templates/class.go.tmpl b/cmd/ego-gen/templates/class.go.tmpl
index 3dcdbf0..f773821 100644
--- a/cmd/ego-gen/templates/class.go.tmpl
+++ b/cmd/ego-gen/templates/class.go.tmpl
@@ -106,6 +106,18 @@ static {{index $im.StructCFieldTypes $i}} _ego_iter_{{$im.StructCType}}_{{$f}}(c
 {{- end}}{{- end}}
 {{- end}}
 
+{{- if .HasCallbacks}}
+// Callback trampoline forward declarations.
+extern void egoCallbackFree(void *data);
+{{- range .CallbackTypes}}
+{{- if .ReturnCType}}
+extern {{.ReturnCType}} {{.GoTrampolineName}}(void *data{{range .Params}}, {{.CType}} {{.GoName}}{{end}});
+{{- else}}
+extern void {{.GoTrampolineName}}(void *data{{range .Params}}, {{.CType}} {{.GoName}}{{end}});
+{{- end}}
+{{- end}}
+{{- end}}
+
 {{- range .Properties}}
 {{- if and .HasGet (isPointerType .GoType)}}
 // _ego_get_{{.CGetName}} wraps the getter, casting the return value through
@@ -434,7 +446,39 @@ func (o *{{$.GoName}}) {{$prop.GoSetter}}(val {{if $prop.IsEo}}efl.Objecter{{els
 {{- end}}
 {{- range .Methods}}
 
-{{- if .OutParams}}
+{{- if .CallbackParams}}
+{{- $m := .}}
+
+// {{$m.GoName}} calls the {{$m.CName}} method on {{$.GoName}}.
+func (o *{{$.GoName}}) {{$m.GoName}}({{range $i, $p := $m.Params}}{{if $i}}, {{end}}{{$p.GoName}} {{if $p.IsEo}}efl.Objecter{{else}}{{$p.GoType}}{{end}}{{end}}{{if $m.Params}}, {{end}}{{range $i, $cp := $m.CallbackParams}}{{if $i}}, {{end}}{{$cp.GoName}} {{$cp.CallbackType.GoFuncType}}{{end}}) {{if $m.ReturnType}}{{$m.ReturnType}}{{end}} {
+{{- range $m.Params}}
+{{- if needsStringConversion .CType}}
+    c{{.GoName}} := C.CString({{.GoName}})
+    defer C.free(unsafe.Pointer(c{{.GoName}}))
+{{- else if isBoolType .CType}}
+    var c{{.GoName}} C.{{cTypeToCgo .CType}}
+    if {{.GoName}} { c{{.GoName}} = 1 }
+{{- end}}
+{{- end}}
+{{- range $m.CallbackParams}}
+    id{{.GoName}} := efl.CallbackRegister({{.GoName}})
+{{- end}}
+{{- if $m.ReturnType}}
+{{- if needsStringConversion $m.ReturnCType}}
+    cResult := C.{{$m.CName}}((*C.Eo)(o.Eo()){{range $m.Params}}, {{template "paramArg" .}}{{end}}{{range $m.CallbackParams}}, unsafe.Pointer(id{{.GoName}}), C.{{.CallbackType.CTypedef}}(C.{{.CallbackType.GoTrampolineName}}), C.Eina_Free_Cb(C.egoCallbackFree){{end}})
+    return C.GoString(cResult)
+{{- else if isBoolType $m.ReturnCType}}
+    return C.{{$m.CName}}((*C.Eo)(o.Eo()){{range $m.Params}}, {{template "paramArg" .}}{{end}}{{range $m.CallbackParams}}, unsafe.Pointer(id{{.GoName}}), C.{{.CallbackType.CTypedef}}(C.{{.CallbackType.GoTrampolineName}}), C.Eina_Free_Cb(C.egoCallbackFree){{end}}) != 0
+{{- else if isPointerType $m.ReturnType}}
+    return unsafe.Pointer(C.{{$m.CName}}((*C.Eo)(o.Eo()){{range $m.Params}}, {{template "paramArg" .}}{{end}}{{range $m.CallbackParams}}, unsafe.Pointer(id{{.GoName}}), C.{{.CallbackType.CTypedef}}(C.{{.CallbackType.GoTrampolineName}}), C.Eina_Free_Cb(C.egoCallbackFree){{end}}))
+{{- else}}
+    return {{$m.ReturnType}}(C.{{$m.CName}}((*C.Eo)(o.Eo()){{range $m.Params}}, {{template "paramArg" .}}{{end}}{{range $m.CallbackParams}}, unsafe.Pointer(id{{.GoName}}), C.{{.CallbackType.CTypedef}}(C.{{.CallbackType.GoTrampolineName}}), C.Eina_Free_Cb(C.egoCallbackFree){{end}}))
+{{- end}}
+{{- else}}
+    C.{{$m.CName}}((*C.Eo)(o.Eo()){{range $m.Params}}, {{template "paramArg" .}}{{end}}{{range $m.CallbackParams}}, unsafe.Pointer(id{{.GoName}}), C.{{.CallbackType.CTypedef}}(C.{{.CallbackType.GoTrampolineName}}), C.Eina_Free_Cb(C.egoCallbackFree){{end}})
+{{- end}}
+}
+{{- else if .OutParams}}
 {{- $m := .}}
 {{- range $op := .OutParams}}
 {{- if $op.IsStruct}}
diff --git a/efl/callback_trampolines_gen.go b/efl/callback_trampolines_gen.go
new file mode 100644
index 0000000..85c273c
--- /dev/null
+++ b/efl/callback_trampolines_gen.go
@@ -0,0 +1,95 @@
+// Code generated by ego-gen. DO NOT EDIT.
+
+package efl
+
+/*
+#cgo pkg-config: elementary
+#define EFL_BETA_API_SUPPORT 1
+// Define all EFL_*_PROTECTED macros to expose @protected methods.
+#define EFL_ACCESS_ACTION_PROTECTED 1
+#define EFL_ACCESS_COMPONENT_PROTECTED 1
+#define EFL_ACCESS_EDITABLE_TEXT_PROTECTED 1
+#define EFL_ACCESS_OBJECT_PROTECTED 1
+#define EFL_ACCESS_SELECTION_PROTECTED 1
+#define EFL_ACCESS_TEXT_PROTECTED 1
+#define EFL_ACCESS_VALUE_PROTECTED 1
+#define EFL_ACCESS_WIDGET_ACTION_PROTECTED 1
+#define EFL_CONFIG_GLOBAL_PROTECTED 1
+#define EFL_GFX_HINT_PROTECTED 1
+#define EFL_IO_CLOSER_FD_PROTECTED 1
+#define EFL_IO_COPIER_PROTECTED 1
+#define EFL_IO_POSITIONER_FD_PROTECTED 1
+#define EFL_IO_READER_FD_PROTECTED 1
+#define EFL_IO_READER_PROTECTED 1
+#define EFL_IO_SIZER_FD_PROTECTED 1
+#define EFL_IO_WRITER_FD_PROTECTED 1
+#define EFL_IO_WRITER_PROTECTED 1
+#define EFL_LAYOUT_CALC_PROTECTED 1
+#define EFL_LOOP_PROTECTED 1
+#define EFL_PACK_LAYOUT_PROTECTED 1
+#define EFL_PART_PROTECTED 1
+#define EFL_UI_FACTORY_PROTECTED 1
+#define EFL_UI_FOCUS_COMPOSITION_PROTECTED 1
+#define EFL_UI_FOCUS_LAYER_PROTECTED 1
+#define EFL_UI_FOCUS_OBJECT_PROTECTED 1
+#define EFL_UI_FORMAT_PROTECTED 1
+#define EFL_UI_L10N_PROTECTED 1
+#define EFL_UI_SCROLLBAR_PROTECTED 1
+#define EFL_UI_SCROLL_MANAGER_PROTECTED 1
+#define EFL_UI_WIDGET_FOCUS_MANAGER_PROTECTED 1
+#define EFL_UI_WIDGET_PROTECTED 1
+#define EFL_UI_WIDGET_SCROLLABLE_CONTENT_PROTECTED 1
+#define EFL_CANVAS_GESTURE_PROTECTED 1
+#define EFL_CANVAS_GESTURE_CUSTOM_PROTECTED 1
+#define EFL_CANVAS_GROUP_PROTECTED 1
+#define EFL_CANVAS_OBJECT_PROTECTED 1
+#define EFL_INPUT_CLICKABLE_PROTECTED 1
+#include <Efl_Ui.h>
+*/
+import "C"
+
+import "unsafe"
+
+// Ensure unused imports are not flagged.
+var _ = unsafe.Pointer(nil)
+
+//export egoCallbackFree
+func egoCallbackFree(data unsafe.Pointer) {
+	CallbackRemove(uintptr(data))
+}
+
+//export egoCallback_EflFilterModel
+func egoCallback_EflFilterModel(data unsafe.Pointer, parent *C.Eo, child *C.Eo) {
+	fn := CallbackLookup[func(unsafe.Pointer, unsafe.Pointer)](uintptr(data))
+	if fn == nil {
+		return
+	}
+	fn(unsafe.Pointer(parent), unsafe.Pointer(child))
+}
+
+//export egoCallback_EflLayoutSignalCb
+func egoCallback_EflLayoutSignalCb(data unsafe.Pointer, object *C.Eo, emission *C.char, source *C.char) {
+	fn := CallbackLookup[func(unsafe.Pointer, string, string)](uintptr(data))
+	if fn == nil {
+		return
+	}
+	fn(unsafe.Pointer(object), C.GoString(emission), C.GoString(source))
+}
+
+//export egoCallback_EflThreadIOCall
+func egoCallback_EflThreadIOCall(data unsafe.Pointer, event unsafe.Pointer) {
+	fn := CallbackLookup[func(unsafe.Pointer)](uintptr(data))
+	if fn == nil {
+		return
+	}
+	fn(event)
+}
+
+//export egoCallback_EflThreadIOCallSync
+func egoCallback_EflThreadIOCallSync(data unsafe.Pointer, event unsafe.Pointer) {
+	fn := CallbackLookup[func(unsafe.Pointer)](uintptr(data))
+	if fn == nil {
+		return
+	}
+	fn(event)
+}
diff --git a/efl/canvas/layout.go b/efl/canvas/layout.go
index 61f410e..88103fc 100644
--- a/efl/canvas/layout.go
+++ b/efl/canvas/layout.go
@@ -131,6 +131,9 @@ static Eina_Bool _ego_iter_next(Eina_Iterator *iter, void **data) {
 static void _ego_iter_free(Eina_Iterator *iter) {
     eina_iterator_free(iter);
 }
+// Callback trampoline forward declarations.
+extern void egoCallbackFree(void *data);
+extern void egoCallback_EflLayoutSignalCb(void *data, Efl_Layout_Signal * object, const char * emission, const char * source);
 // _ego_get_efl_canvas_layout_load_error_get wraps the getter, casting the return value through
 // uintptr_t so that both pointer and integer returns become void *.
 // This prevents C type conflicts when Eolian's type differs from the header.
@@ -525,6 +528,26 @@ func (o *Layout) CalcForce() {
 	C.efl_layout_calc_force((*C.Eo)(o.Eo()))
 }
 
+// SignalCallbackAdd calls the efl_layout_signal_callback_add method on Layout.
+func (o *Layout) SignalCallbackAdd(emission string, source string, func_ func(unsafe.Pointer, string, string)) bool {
+	cemission := C.CString(emission)
+	defer C.free(unsafe.Pointer(cemission))
+	csource := C.CString(source)
+	defer C.free(unsafe.Pointer(csource))
+	idfunc_ := efl.CallbackRegister(func_)
+	return C.efl_layout_signal_callback_add((*C.Eo)(o.Eo()), cemission, csource, unsafe.Pointer(idfunc_), C.EflLayoutSignalCb(C.egoCallback_EflLayoutSignalCb), C.Eina_Free_Cb(C.egoCallbackFree)) != 0
+}
+
+// SignalCallbackDel calls the efl_layout_signal_callback_del method on Layout.
+func (o *Layout) SignalCallbackDel(emission string, source string, func_ func(unsafe.Pointer, string, string)) bool {
+	cemission := C.CString(emission)
+	defer C.free(unsafe.Pointer(cemission))
+	csource := C.CString(source)
+	defer C.free(unsafe.Pointer(csource))
+	idfunc_ := efl.CallbackRegister(func_)
+	return C.efl_layout_signal_callback_del((*C.Eo)(o.Eo()), cemission, csource, unsafe.Pointer(idfunc_), C.EflLayoutSignalCb(C.egoCallback_EflLayoutSignalCb), C.Eina_Free_Cb(C.egoCallbackFree)) != 0
+}
+
 // SignalEmit calls the efl_layout_signal_emit method on Layout.
 func (o *Layout) SignalEmit(emission string, source string) {
 	cemission := C.CString(emission)
diff --git a/efl/eo/appthread.go b/efl/eo/appthread.go
index eede53a..6f75874 100644
--- a/efl/eo/appthread.go
+++ b/efl/eo/appthread.go
@@ -99,6 +99,10 @@ typedef Eo Efl_Ui_Widget;
 // Declare the class_get function directly rather than including the full .eo.h
 // header, which may reference types from other .eo files that are not included.
 extern const Efl_Class *efl_appthread_class_get(void);
+// Callback trampoline forward declarations.
+extern void egoCallbackFree(void *data);
+extern void egoCallback_EflThreadIOCall(void *data, const Efl_Event * event);
+extern void egoCallback_EflThreadIOCallSync(void *data, const Efl_Event * event);
 // _ego_get_efl_threadio_indata_get wraps the getter, casting the return value through
 // uintptr_t so that both pointer and integer returns become void *.
 // This prevents C type conflicts when Eolian's type differs from the header.
@@ -310,6 +314,18 @@ func (o *Appthread) SetCommandString(val string) {
 	C.efl_core_command_line_command_string_set((*C.Eo)(o.Eo()), cVal)
 }
 
+// Call calls the efl_threadio_call method on Appthread.
+func (o *Appthread) Call(func_ func(unsafe.Pointer)) {
+	idfunc_ := efl.CallbackRegister(func_)
+	C.efl_threadio_call((*C.Eo)(o.Eo()), unsafe.Pointer(idfunc_), C.EflThreadIOCall(C.egoCallback_EflThreadIOCall), C.Eina_Free_Cb(C.egoCallbackFree))
+}
+
+// CallSync calls the efl_threadio_call_sync method on Appthread.
+func (o *Appthread) CallSync(func_ func(unsafe.Pointer)) unsafe.Pointer {
+	idfunc_ := efl.CallbackRegister(func_)
+	return unsafe.Pointer(C.efl_threadio_call_sync((*C.Eo)(o.Eo()), unsafe.Pointer(idfunc_), C.EflThreadIOCallSync(C.egoCallback_EflThreadIOCallSync), C.Eina_Free_Cb(C.egoCallbackFree)))
+}
+
 // CommandAccess calls the efl_core_command_line_command_access method on Appthread.
 func (o *Appthread) CommandAccess() unsafe.Pointer {
 	return unsafe.Pointer(C.efl_core_command_line_command_access((*C.Eo)(o.Eo())))
diff --git a/efl/eo/filter_model.go b/efl/eo/filter_model.go
index 857bcab..04585fb 100644
--- a/efl/eo/filter_model.go
+++ b/efl/eo/filter_model.go
@@ -84,6 +84,9 @@ typedef Eo Efl_Ui_Widget;
 // Declare the class_get function directly rather than including the full .eo.h
 // header, which may reference types from other .eo files that are not included.
 extern const Efl_Class *efl_filter_model_class_get(void);
+// Callback trampoline forward declarations.
+extern void egoCallbackFree(void *data);
+extern void egoCallback_EflFilterModel(void *data, Efl_Filter_Model * parent, Efl_Model * child);
 */
 import "C"
 
@@ -135,3 +138,9 @@ func NewFilterModel(parent efl.Objecter, opts ...efl.Option) *FilterModel {
 	}
 	return wrapFilterModel(result)
 }
+
+// FilterSet calls the efl_filter_model_filter_set method on FilterModel.
+func (o *FilterModel) FilterSet(filter func(unsafe.Pointer, unsafe.Pointer)) {
+	idfilter := efl.CallbackRegister(filter)
+	C.efl_filter_model_filter_set((*C.Eo)(o.Eo()), unsafe.Pointer(idfilter), C.EflFilterModel(C.egoCallback_EflFilterModel), C.Eina_Free_Cb(C.egoCallbackFree))
+}
diff --git a/efl/eo/thread.go b/efl/eo/thread.go
index de8be32..89d4d80 100644
--- a/efl/eo/thread.go
+++ b/efl/eo/thread.go
@@ -99,6 +99,10 @@ typedef Eo Efl_Ui_Widget;
 // Declare the class_get function directly rather than including the full .eo.h
 // header, which may reference types from other .eo files that are not included.
 extern const Efl_Class *efl_thread_class_get(void);
+// Callback trampoline forward declarations.
+extern void egoCallbackFree(void *data);
+extern void egoCallback_EflThreadIOCall(void *data, const Efl_Event * event);
+extern void egoCallback_EflThreadIOCallSync(void *data, const Efl_Event * event);
 // _ego_get_efl_threadio_indata_get wraps the getter, casting the return value through
 // uintptr_t so that both pointer and integer returns become void *.
 // This prevents C type conflicts when Eolian's type differs from the header.
@@ -310,6 +314,18 @@ func (o *Thread) SetCommandString(val string) {
 	C.efl_core_command_line_command_string_set((*C.Eo)(o.Eo()), cVal)
 }
 
+// Call calls the efl_threadio_call method on Thread.
+func (o *Thread) Call(func_ func(unsafe.Pointer)) {
+	idfunc_ := efl.CallbackRegister(func_)
+	C.efl_threadio_call((*C.Eo)(o.Eo()), unsafe.Pointer(idfunc_), C.EflThreadIOCall(C.egoCallback_EflThreadIOCall), C.Eina_Free_Cb(C.egoCallbackFree))
+}
+
+// CallSync calls the efl_threadio_call_sync method on Thread.
+func (o *Thread) CallSync(func_ func(unsafe.Pointer)) unsafe.Pointer {
+	idfunc_ := efl.CallbackRegister(func_)
+	return unsafe.Pointer(C.efl_threadio_call_sync((*C.Eo)(o.Eo()), unsafe.Pointer(idfunc_), C.EflThreadIOCallSync(C.egoCallback_EflThreadIOCallSync), C.Eina_Free_Cb(C.egoCallbackFree)))
+}
+
 // CommandAccess calls the efl_core_command_line_command_access method on Thread.
 func (o *Thread) CommandAccess() unsafe.Pointer {
 	return unsafe.Pointer(C.efl_core_command_line_command_access((*C.Eo)(o.Eo())))
diff --git a/efl/eo/thread_io.go b/efl/eo/thread_io.go
index 22b6941..dab5165 100644
--- a/efl/eo/thread_io.go
+++ b/efl/eo/thread_io.go
@@ -84,6 +84,10 @@ typedef Eo Efl_Ui_Widget;
 // Declare the class_get function directly rather than including the full .eo.h
 // header, which may reference types from other .eo files that are not included.
 extern const Efl_Class *efl_threadio_mixin_get(void);
+// Callback trampoline forward declarations.
+extern void egoCallbackFree(void *data);
+extern void egoCallback_EflThreadIOCall(void *data, const Efl_Event * event);
+extern void egoCallback_EflThreadIOCallSync(void *data, const Efl_Event * event);
 // _ego_get_efl_threadio_indata_get wraps the getter, casting the return value through
 // uintptr_t so that both pointer and integer returns become void *.
 // This prevents C type conflicts when Eolian's type differs from the header.
@@ -154,3 +158,15 @@ func (o *ThreadIO) Outdata() unsafe.Pointer {
 func (o *ThreadIO) SetOutdata(val unsafe.Pointer) {
 	C._ego_set_efl_threadio_outdata_set((*C.Eo)(o.Eo()), val)
 }
+
+// Call calls the efl_threadio_call method on ThreadIO.
+func (o *ThreadIO) Call(func_ func(unsafe.Pointer)) {
+	idfunc_ := efl.CallbackRegister(func_)
+	C.efl_threadio_call((*C.Eo)(o.Eo()), unsafe.Pointer(idfunc_), C.EflThreadIOCall(C.egoCallback_EflThreadIOCall), C.Eina_Free_Cb(C.egoCallbackFree))
+}
+
+// CallSync calls the efl_threadio_call_sync method on ThreadIO.
+func (o *ThreadIO) CallSync(func_ func(unsafe.Pointer)) unsafe.Pointer {
+	idfunc_ := efl.CallbackRegister(func_)
+	return unsafe.Pointer(C.efl_threadio_call_sync((*C.Eo)(o.Eo()), unsafe.Pointer(idfunc_), C.EflThreadIOCallSync(C.egoCallback_EflThreadIOCallSync), C.Eina_Free_Cb(C.egoCallbackFree)))
+}
diff --git a/efl/layout/signal.go b/efl/layout/signal.go
index 49c0b19..5b86a20 100644
--- a/efl/layout/signal.go
+++ b/efl/layout/signal.go
@@ -84,6 +84,9 @@ typedef Eo Efl_Ui_Widget;
 // Declare the class_get function directly rather than including the full .eo.h
 // header, which may reference types from other .eo files that are not included.
 extern const Efl_Class *efl_layout_signal_interface_get(void);
+// Callback trampoline forward declarations.
+extern void egoCallbackFree(void *data);
+extern void egoCallback_EflLayoutSignalCb(void *data, Efl_Layout_Signal * object, const char * emission, const char * source);
 */
 import "C"
 
@@ -109,6 +112,26 @@ func wrapSignal(ptr unsafe.Pointer) *Signal {
 	return o
 }
 
+// SignalCallbackAdd calls the efl_layout_signal_callback_add method on Signal.
+func (o *Signal) SignalCallbackAdd(emission string, source string, func_ func(unsafe.Pointer, string, string)) bool {
+	cemission := C.CString(emission)
+	defer C.free(unsafe.Pointer(cemission))
+	csource := C.CString(source)
+	defer C.free(unsafe.Pointer(csource))
+	idfunc_ := efl.CallbackRegister(func_)
+	return C.efl_layout_signal_callback_add((*C.Eo)(o.Eo()), cemission, csource, unsafe.Pointer(idfunc_), C.EflLayoutSignalCb(C.egoCallback_EflLayoutSignalCb), C.Eina_Free_Cb(C.egoCallbackFree)) != 0
+}
+
+// SignalCallbackDel calls the efl_layout_signal_callback_del method on Signal.
+func (o *Signal) SignalCallbackDel(emission string, source string, func_ func(unsafe.Pointer, string, string)) bool {
+	cemission := C.CString(emission)
+	defer C.free(unsafe.Pointer(cemission))
+	csource := C.CString(source)
+	defer C.free(unsafe.Pointer(csource))
+	idfunc_ := efl.CallbackRegister(func_)
+	return C.efl_layout_signal_callback_del((*C.Eo)(o.Eo()), cemission, csource, unsafe.Pointer(idfunc_), C.EflLayoutSignalCb(C.egoCallback_EflLayoutSignalCb), C.Eina_Free_Cb(C.egoCallbackFree)) != 0
+}
+
 // SignalEmit calls the efl_layout_signal_emit method on Signal.
 func (o *Signal) SignalEmit(emission string, source string) {
 	cemission := C.CString(emission)
diff --git a/efl/ui/image.go b/efl/ui/image.go
index 258bd07..6f15653 100644
--- a/efl/ui/image.go
+++ b/efl/ui/image.go
@@ -141,6 +141,9 @@ typedef Eo Efl_Ui_Widget;
 // Declare the class_get function directly rather than including the full .eo.h
 // header, which may reference types from other .eo files that are not included.
 extern const Efl_Class *efl_ui_image_class_get(void);
+// Callback trampoline forward declarations.
+extern void egoCallbackFree(void *data);
+extern void egoCallback_EflLayoutSignalCb(void *data, Efl_Layout_Signal * object, const char * emission, const char * source);
 // _ego_get_efl_gfx_image_scale_method_get wraps the getter, casting the return value through
 // uintptr_t so that both pointer and integer returns become void *.
 // This prevents C type conflicts when Eolian's type differs from the header.
@@ -1183,6 +1186,26 @@ func (o *Image) CalcForce() {
 	C.efl_layout_calc_force((*C.Eo)(o.Eo()))
 }
 
+// SignalCallbackAdd calls the efl_layout_signal_callback_add method on Image.
+func (o *Image) SignalCallbackAdd(emission string, source string, func_ func(unsafe.Pointer, string, string)) bool {
+	cemission := C.CString(emission)
+	defer C.free(unsafe.Pointer(cemission))
+	csource := C.CString(source)
+	defer C.free(unsafe.Pointer(csource))
+	idfunc_ := efl.CallbackRegister(func_)
+	return C.efl_layout_signal_callback_add((*C.Eo)(o.Eo()), cemission, csource, unsafe.Pointer(idfunc_), C.EflLayoutSignalCb(C.egoCallback_EflLayoutSignalCb), C.Eina_Free_Cb(C.egoCallbackFree)) != 0
+}
+
+// SignalCallbackDel calls the efl_layout_signal_callback_del method on Image.
+func (o *Image) SignalCallbackDel(emission string, source string, func_ func(unsafe.Pointer, string, string)) bool {
+	cemission := C.CString(emission)
+	defer C.free(unsafe.Pointer(cemission))
+	csource := C.CString(source)
+	defer C.free(unsafe.Pointer(csource))
+	idfunc_ := efl.CallbackRegister(func_)
+	return C.efl_layout_signal_callback_del((*C.Eo)(o.Eo()), cemission, csource, unsafe.Pointer(idfunc_), C.EflLayoutSignalCb(C.egoCallback_EflLayoutSignalCb), C.Eina_Free_Cb(C.egoCallbackFree)) != 0
+}
+
 // SignalEmit calls the efl_layout_signal_emit method on Image.
 func (o *Image) SignalEmit(emission string, source string) {
 	cemission := C.CString(emission)
diff --git a/efl/ui/layout_base.go b/efl/ui/layout_base.go
index dce39e7..ada9ad8 100644
--- a/efl/ui/layout_base.go
+++ b/efl/ui/layout_base.go
@@ -107,6 +107,9 @@ static Eina_Bool _ego_iter_next(Eina_Iterator *iter, void **data) {
 static void _ego_iter_free(Eina_Iterator *iter) {
     eina_iterator_free(iter);
 }
+// Callback trampoline forward declarations.
+extern void egoCallbackFree(void *data);
+extern void egoCallback_EflLayoutSignalCb(void *data, Efl_Layout_Signal * object, const char * emission, const char * source);
 // _ego_get_struct_efl_layout_group_size_min_get wraps the getter, decomposing the returned
 // struct into individual out-params for safe cgo consumption.
 static void _ego_get_struct_efl_layout_group_size_min_get(const Eo *obj, int *out_w, int *out_h) {
@@ -279,6 +282,26 @@ func (o *LayoutBase) CalcForce() {
 	C.efl_layout_calc_force((*C.Eo)(o.Eo()))
 }
 
+// SignalCallbackAdd calls the efl_layout_signal_callback_add method on LayoutBase.
+func (o *LayoutBase) SignalCallbackAdd(emission string, source string, func_ func(unsafe.Pointer, string, string)) bool {
+	cemission := C.CString(emission)
+	defer C.free(unsafe.Pointer(cemission))
+	csource := C.CString(source)
+	defer C.free(unsafe.Pointer(csource))
+	idfunc_ := efl.CallbackRegister(func_)
+	return C.efl_layout_signal_callback_add((*C.Eo)(o.Eo()), cemission, csource, unsafe.Pointer(idfunc_), C.EflLayoutSignalCb(C.egoCallback_EflLayoutSignalCb), C.Eina_Free_Cb(C.egoCallbackFree)) != 0
+}
+
+// SignalCallbackDel calls the efl_layout_signal_callback_del method on LayoutBase.
+func (o *LayoutBase) SignalCallbackDel(emission string, source string, func_ func(unsafe.Pointer, string, string)) bool {
+	cemission := C.CString(emission)
+	defer C.free(unsafe.Pointer(cemission))
+	csource := C.CString(source)
+	defer C.free(unsafe.Pointer(csource))
+	idfunc_ := efl.CallbackRegister(func_)
+	return C.efl_layout_signal_callback_del((*C.Eo)(o.Eo()), cemission, csource, unsafe.Pointer(idfunc_), C.EflLayoutSignalCb(C.egoCallback_EflLayoutSignalCb), C.Eina_Free_Cb(C.egoCallbackFree)) != 0
+}
+
 // SignalEmit calls the efl_layout_signal_emit method on LayoutBase.
 func (o *LayoutBase) SignalEmit(emission string, source string) {
 	cemission := C.CString(emission)

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to