v0.10.0 0f4e9eb

workspace_widgets_stub.go RawHistoryFolder

1//go:build !webkit_cgo
2
3package webkit
4
5import "sync"
6
7// Orientation mirrors GtkOrientation in stub builds.
8type Orientation int
9
10const (
11	OrientationHorizontal Orientation = 0
12	OrientationVertical   Orientation = 1
13)
14
15// WidgetBounds mirrors the CGO struct for stub builds.
16type WidgetBounds struct {
17	X      float64
18	Y      float64
19	Width  float64
20	Height float64
21}
22
23type widgetStub struct {
24	startChild uintptr
25	endChild   uintptr
26	bounds     WidgetBounds
27	hasBounds  bool
28	hover      map[uintptr]func()
29}
30
31var (
32	widgetMu       sync.Mutex
33	widgetState            = map[uintptr]*widgetStub{}
34	nextWidgetID   uintptr = 1
35	nextHoverToken uintptr = 1
36)
37
38func newWidgetHandle() uintptr {
39	widgetMu.Lock()
40	defer widgetMu.Unlock()
41	id := nextWidgetID
42	nextWidgetID++
43	widgetState[id] = &widgetStub{}
44	return id
45}
46
47// NewTestWidget returns a unique widget handle for tests.
48func NewTestWidget() uintptr { return newWidgetHandle() }
49
50// SetWidgetBoundsForTesting assigns bounds for the widget in stub builds.
51func SetWidgetBoundsForTesting(widget uintptr, bounds WidgetBounds) {
52	widgetMu.Lock()
53	defer widgetMu.Unlock()
54	stub, ok := widgetState[widget]
55	if !ok {
56		stub = &widgetStub{}
57		widgetState[widget] = stub
58	}
59	stub.bounds = bounds
60	stub.hasBounds = true
61}
62
63// ResetWidgetStubsForTesting clears widget stub state for deterministic tests.
64func ResetWidgetStubsForTesting() {
65	widgetMu.Lock()
66	defer widgetMu.Unlock()
67	widgetState = map[uintptr]*widgetStub{}
68	nextWidgetID = 1
69	nextHoverToken = 1
70}
71
72func NewPaned(orientation Orientation) uintptr {
73	return newWidgetHandle()
74}
75
76func PanedSetStartChild(paned uintptr, child uintptr) {
77	widgetMu.Lock()
78	defer widgetMu.Unlock()
79	if stub, ok := widgetState[paned]; ok {
80		stub.startChild = child
81	}
82}
83
84func PanedSetEndChild(paned uintptr, child uintptr) {
85	widgetMu.Lock()
86	defer widgetMu.Unlock()
87	if stub, ok := widgetState[paned]; ok {
88		stub.endChild = child
89	}
90}
91
92func PanedSetResizeStart(paned uintptr, resize bool) {}
93
94func PanedSetResizeEnd(paned uintptr, resize bool) {}
95
96// PanedSetPosition is a no-op in stub builds.
97func PanedSetPosition(paned uintptr, pos int) {}
98
99func WidgetUnparent(widget uintptr) {}
100
101func WidgetSetHExpand(widget uintptr, expand bool) {}
102
103func WidgetSetVExpand(widget uintptr, expand bool) {}
104
105func WidgetGetParent(widget uintptr) uintptr { return 0 }
106
107func WidgetShow(widget uintptr) {}
108
109func WidgetGrabFocus(widget uintptr) {}
110
111func WidgetRef(widget uintptr) bool {
112	widgetMu.Lock()
113	defer widgetMu.Unlock()
114	_, ok := widgetState[widget]
115	return ok
116}
117
118func WidgetUnref(widget uintptr) {}
119
120func WidgetQueueAllocate(widget uintptr) {}
121
122func WidgetRealizeInContainer(widget uintptr) {}
123
124func WidgetHookDestroy(widget uintptr) {}
125
126func WidgetIsValid(widget uintptr) bool {
127	widgetMu.Lock()
128	defer widgetMu.Unlock()
129	_, ok := widgetState[widget]
130	return ok && widget != 0
131}
132
133func WidgetRefCount(widget uintptr) uint {
134	if WidgetIsValid(widget) {
135		return 1
136	}
137	return 0
138}
139
140func WidgetAddHoverHandler(widget uintptr, fn func()) uintptr {
141	if widget == 0 || fn == nil {
142		return 0
143	}
144	widgetMu.Lock()
145	defer widgetMu.Unlock()
146	stub, ok := widgetState[widget]
147	if !ok {
148		stub = &widgetStub{}
149		widgetState[widget] = stub
150	}
151	if stub.hover == nil {
152		stub.hover = make(map[uintptr]func())
153	}
154	token := nextHoverToken
155	nextHoverToken++
156	stub.hover[token] = fn
157	return token
158}
159
160func WidgetRemoveHoverHandler(widget uintptr, token uintptr) {
161	widgetMu.Lock()
162	defer widgetMu.Unlock()
163	if stub, ok := widgetState[widget]; ok && stub.hover != nil {
164		delete(stub.hover, token)
165	}
166}
167
168func WidgetGetBounds(widget uintptr) (WidgetBounds, bool) {
169	widgetMu.Lock()
170	defer widgetMu.Unlock()
171	stub, ok := widgetState[widget]
172	if !ok || !stub.hasBounds {
173		return WidgetBounds{}, false
174	}
175	return stub.bounds, true
176}
177
178func IdleAdd(fn func() bool) {
179	if fn != nil {
180		fn()
181	}
182}
183
184func AddCSSProvider(css string) {}
185
186func WidgetAddCSSClass(widget uintptr, class string) {}
187
188func WidgetRemoveCSSClass(widget uintptr, class string) {}

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