v0.12.0 d035193

helpers.go RawHistoryFolder

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}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close