1package webkit
2
3import (
4 "github.com/diamondburned/gotk4/pkg/gdk/v4"
5 "github.com/diamondburned/gotk4/pkg/glib/v2"
6 "github.com/diamondburned/gotk4/pkg/gtk/v4"
7)
8
9// IsNativeAvailable returns true if the native GTK/WebKit libraries are available
10// In gotk4, this is always true if the import succeeded
11func IsNativeAvailable() bool {
12 return true
13}
14
15// IdleAdd adds a function to be called in an idle callback
16// Returns an idle source ID that can be used with IdleRemove
17func IdleAdd(fn func() bool) uint {
18 return uint(glib.IdleAdd(fn))
19}
20
21// IdleRemove removes an idle callback by its source ID
22func IdleRemove(sourceID uint) {
23 glib.SourceRemove(glib.SourceHandle(sourceID))
24}
25
26// WidgetIsValid checks if a widget pointer is valid (non-nil)
27func WidgetIsValid(w gtk.Widgetter) bool {
28 return w != nil
29}
30
31// WidgetSetMargin sets all margins for a widget
32func WidgetSetMargin(w gtk.Widgetter, margin int) {
33 if widget := getWidget(w); widget != nil {
34 widget.SetMarginStart(margin)
35 widget.SetMarginEnd(margin)
36 widget.SetMarginTop(margin)
37 widget.SetMarginBottom(margin)
38 }
39}
40
41// WidgetSetMarginTop sets the top margin for a widget
42func WidgetSetMarginTop(w gtk.Widgetter, margin int) {
43 if widget := getWidget(w); widget != nil {
44 widget.SetMarginTop(margin)
45 }
46}
47
48// WidgetSetMarginBottom sets the bottom margin for a widget
49func WidgetSetMarginBottom(w gtk.Widgetter, margin int) {
50 if widget := getWidget(w); widget != nil {
51 widget.SetMarginBottom(margin)
52 }
53}
54
55// WidgetSetMarginStart sets the start margin for a widget
56func WidgetSetMarginStart(w gtk.Widgetter, margin int) {
57 if widget := getWidget(w); widget != nil {
58 widget.SetMarginStart(margin)
59 }
60}
61
62// WidgetSetMarginEnd sets the end margin for a widget
63func WidgetSetMarginEnd(w gtk.Widgetter, margin int) {
64 if widget := getWidget(w); widget != nil {
65 widget.SetMarginEnd(margin)
66 }
67}
68
69// WidgetAddCSSClass adds a CSS class to a widget
70func WidgetAddCSSClass(w gtk.Widgetter, className string) {
71 if widget := getWidget(w); widget != nil {
72 widget.AddCSSClass(className)
73 }
74}
75
76// WidgetRemoveCSSClass removes a CSS class from a widget
77func WidgetRemoveCSSClass(w gtk.Widgetter, className string) {
78 if widget := getWidget(w); widget != nil {
79 widget.RemoveCSSClass(className)
80 }
81}
82
83// WidgetHasCSSClass checks if a widget has a CSS class
84func WidgetHasCSSClass(w gtk.Widgetter, className string) bool {
85 if widget := getWidget(w); widget != nil {
86 return widget.HasCSSClass(className)
87 }
88 return false
89}
90
91// WidgetSetHExpand sets whether the widget should expand horizontally
92func WidgetSetHExpand(w gtk.Widgetter, expand bool) {
93 if widget := getWidget(w); widget != nil {
94 widget.SetHExpand(expand)
95 }
96}
97
98// WidgetSetVExpand sets whether the widget should expand vertically
99func WidgetSetVExpand(w gtk.Widgetter, expand bool) {
100 if widget := getWidget(w); widget != nil {
101 widget.SetVExpand(expand)
102 }
103}
104
105// WidgetRealizeInContainer realizes a widget within a container
106func WidgetRealizeInContainer(w gtk.Widgetter, container gtk.Widgetter) {
107 if widget := getWidget(w); widget != nil {
108 widget.Realize()
109 }
110}
111
112// WidgetRealize realizes a widget
113func WidgetRealize(w gtk.Widgetter) {
114 if widget := getWidget(w); widget != nil {
115 widget.Realize()
116 }
117}
118
119// WidgetGetParent returns the parent widget
120func WidgetGetParent(w gtk.Widgetter) gtk.Widgetter {
121 if widget := getWidget(w); widget != nil {
122 return widget.Parent()
123 }
124 return nil
125}
126
127// WidgetUnparent removes a widget from its parent
128func WidgetUnparent(w gtk.Widgetter) {
129 if widget := getWidget(w); widget != nil {
130 widget.Unparent()
131 }
132}
133
134// WidgetQueueAllocate queues an allocate operation
135func WidgetQueueAllocate(w gtk.Widgetter) {
136 if widget := getWidget(w); widget != nil {
137 widget.QueueAllocate()
138 }
139}
140
141// WidgetQueueDraw queues a redraw operation
142func WidgetQueueDraw(w gtk.Widgetter) {
143 if widget := getWidget(w); widget != nil {
144 widget.QueueDraw()
145 }
146}
147
148// WidgetGetAllocation returns the widget's allocated area
149func WidgetGetAllocation(w gtk.Widgetter) (x, y, width, height int) {
150 if widget := getWidget(w); widget != nil {
151 alloc := widget.Allocation()
152 return alloc.X(), alloc.Y(), alloc.Width(), alloc.Height()
153 }
154 return 0, 0, 0, 0
155}
156
157// WidgetGetBounds returns the widget's bounds relative to its parent
158func WidgetGetBounds(w gtk.Widgetter) (x, y, width, height float64) {
159 if widget := getWidget(w); widget != nil {
160 parent := widget.Parent()
161 if parent != nil {
162 rect, ok := widget.ComputeBounds(parent)
163 if ok && rect != nil {
164 // Get bounds directly from graphene.Rect
165 return float64(rect.X()), float64(rect.Y()),
166 float64(rect.Width()), float64(rect.Height())
167 }
168 }
169 }
170 return 0, 0, 0, 0
171}
172
173// WidgetSetFocusChild sets the focus child of a widget
174func WidgetSetFocusChild(w gtk.Widgetter, child gtk.Widgetter) {
175 if widget := getWidget(w); widget != nil {
176 widget.SetFocusChild(child)
177 }
178}
179
180// WidgetAddFocusController adds a focus event controller to a widget
181func WidgetAddFocusController(w gtk.Widgetter, onEnter, onLeave func()) *gtk.EventControllerFocus {
182 if widget := getWidget(w); widget != nil {
183 controller := gtk.NewEventControllerFocus()
184 if onEnter != nil {
185 controller.ConnectEnter(onEnter)
186 }
187 if onLeave != nil {
188 controller.ConnectLeave(onLeave)
189 }
190 widget.AddController(controller)
191 return controller
192 }
193 return nil
194}
195
196// WidgetRemoveFocusController removes a focus event controller from a widget
197func WidgetRemoveFocusController(w gtk.Widgetter, controller *gtk.EventControllerFocus) {
198 if widget := getWidget(w); widget != nil && controller != nil {
199 widget.RemoveController(controller)
200 }
201}
202
203// WidgetAddHoverHandler registers a hover callback for the given widget and
204// returns a controller that can be used to detach it later.
205func WidgetAddHoverHandler(w gtk.Widgetter, fn func()) *gtk.EventControllerMotion {
206 if widget := getWidget(w); widget != nil && fn != nil {
207 motion := gtk.NewEventControllerMotion()
208 motion.SetPropagationPhase(gtk.PhaseCapture)
209
210 // Connect to enter signal - triggered when mouse enters the widget
211 motion.ConnectEnter(func(x, y float64) {
212 fn()
213 })
214
215 widget.AddController(motion)
216 return motion
217 }
218 return nil
219}
220
221// WidgetRemoveHoverHandler removes a previously registered hover controller
222func WidgetRemoveHoverHandler(w gtk.Widgetter, controller *gtk.EventControllerMotion) {
223 if widget := getWidget(w); widget != nil && controller != nil {
224 widget.RemoveController(controller)
225 }
226}
227
228// WidgetAddController adds an event controller to a widget
229func WidgetAddController(w gtk.Widgetter, controller gtk.EventControllerer) {
230 if widget := getWidget(w); widget != nil && controller != nil {
231 widget.AddController(controller)
232 }
233}
234
235// WidgetAllocation returns the widget's allocation (alias for WidgetGetAllocation)
236func WidgetAllocation(w gtk.Widgetter) (x, y, width, height int) {
237 return WidgetGetAllocation(w)
238}
239
240// PrefersDarkTheme checks if the system prefers dark theme
241func PrefersDarkTheme() bool {
242 settings := gtk.SettingsGetDefault()
243 if settings != nil {
244 // In GTK4, check the color scheme preference
245 // The property is "gtk-application-prefer-dark-theme"
246 obj := settings.Object
247 if obj != nil {
248 prop := obj.ObjectProperty("gtk-application-prefer-dark-theme")
249 if v, ok := prop.(bool); ok && v {
250 return true
251 }
252 }
253 }
254 return false
255}
256
257// AddCSSProvider adds a CSS provider for styling
258func AddCSSProvider(css string) error {
259 provider := gtk.NewCSSProvider()
260 provider.LoadFromString(css)
261
262 gtk.StyleContextAddProviderForDisplay(
263 gdk.DisplayGetDefault(),
264 provider,
265 gtk.STYLE_PROVIDER_PRIORITY_APPLICATION,
266 )
267
268 return nil
269}