detached 364f051

refactor(browser): migrate workspace_utils.go to gotk4 API

commit
364f0513024d967251e587307e8c7ddc3c350d48
author
bamen · · 2025-10-09 05:39 UTC
parent
99570ca
signature
unsigned
1 file · +29 -22
M internal/app/browser/workspace_utils.go +29 -22
@@ -6,6 +6,7 @@ import (
66 "log"
77
88 "github.com/bnema/dumber/pkg/webkit"
9+ "github.com/diamondburned/gotk4/pkg/glib/v2"
910 "github.com/diamondburned/gotk4/pkg/gtk/v4"
1011 )
1112
@@ -98,10 +99,10 @@ func (wm *WorkspaceManager) setStackWrapper(node *paneNode, widget gtk.Widgetter
9899
99100 // PaneBorderContext holds the context for applying borders to any pane type
100101 type PaneBorderContext struct {
101- webViewWidget uintptr // The WebView's native widget (for margin)
102- borderContainer uintptr // The container that gets background color
103- cssClasses []string // Additional CSS classes to apply
104- paneType string // Description for debugging
102+ webViewWidget gtk.Widgetter // The WebView's native widget (for margin)
103+ borderContainer gtk.Widgetter // The container that gets background color
104+ cssClasses []string // Additional CSS classes to apply
105+ paneType string // Description for debugging
105106 }
106107
107108 // determineBorderContext analyzes a pane node and determines the correct border context
@@ -155,18 +156,21 @@ func (wm *WorkspaceManager) applyActivePaneBorder(ctx *PaneBorderContext) {
155156 }
156157
157158 // Apply margin to WebView widget (creates space for border)
158- if ctx.webViewWidget != 0 && webkit.WidgetIsValid(ctx.webViewWidget) {
159- webkit.WidgetSetMargin(ctx.webViewWidget, 2)
159+ if ctx.webViewWidget != nil {
160+ ctx.webViewWidget.SetMarginTop(2)
161+ ctx.webViewWidget.SetMarginBottom(2)
162+ ctx.webViewWidget.SetMarginStart(2)
163+ ctx.webViewWidget.SetMarginEnd(2)
160164 }
161165
162166 // Apply CSS classes to border container
163- if ctx.borderContainer != 0 && webkit.WidgetIsValid(ctx.borderContainer) {
167+ if ctx.borderContainer != nil {
164168 for _, class := range ctx.cssClasses {
165- webkit.WidgetAddCSSClass(ctx.borderContainer, class)
169+ ctx.borderContainer.AddCSSClass(class)
166170 }
167171 }
168172
169- log.Printf("[workspace] Applied active border: type=%s webView=%#x container=%#x",
173+ log.Printf("[workspace] Applied active border: type=%s webView=%p container=%p",
170174 ctx.paneType, ctx.webViewWidget, ctx.borderContainer)
171175 }
172176
@@ -182,26 +186,29 @@ func (wm *WorkspaceManager) removeActivePaneBorder(node *paneNode) {
182186 }
183187
184188 // Remove margin from WebView widget
185- if ctx.webViewWidget != 0 && webkit.WidgetIsValid(ctx.webViewWidget) {
186- webkit.WidgetSetMargin(ctx.webViewWidget, 0)
189+ if ctx.webViewWidget != nil {
190+ ctx.webViewWidget.SetMarginTop(0)
191+ ctx.webViewWidget.SetMarginBottom(0)
192+ ctx.webViewWidget.SetMarginStart(0)
193+ ctx.webViewWidget.SetMarginEnd(0)
187194 }
188195
189196 // Remove CSS classes from border container
190- if ctx.borderContainer != 0 && webkit.WidgetIsValid(ctx.borderContainer) {
197+ if ctx.borderContainer != nil {
191198 for _, class := range ctx.cssClasses {
192- webkit.WidgetRemoveCSSClass(ctx.borderContainer, class)
199+ ctx.borderContainer.RemoveCSSClass(class)
193200 }
194201 }
195202
196- log.Printf("[workspace] Removed active border: type=%s webView=%#x container=%#x",
203+ log.Printf("[workspace] Removed active border: type=%s webView=%p container=%p",
197204 ctx.paneType, ctx.webViewWidget, ctx.borderContainer)
198205 }
199206
200207 // Widget cleanup utilities
201208
202209 // cleanupWidget safely invalidates and cleans up a widget
203-func (wm *WorkspaceManager) cleanupWidget(ptr uintptr) {
204- if ptr == 0 {
210+func (wm *WorkspaceManager) cleanupWidget(widget gtk.Widgetter) {
211+ if widget == nil {
205212 return
206213 }
207214
@@ -217,7 +224,7 @@ func (wm *WorkspaceManager) scheduleIdleGuarded(fn func() bool, nodes ...*paneNo
217224 }
218225 guards := uniquePaneNodes(nodes...)
219226 var handle uintptr
220- handle = webkit.IdleAdd(func() bool {
227+ handle = uintptr(glib.IdleAdd(func() bool {
221228 defer wm.releaseIdleHandle(handle)
222229 for _, node := range guards {
223230 if node == nil {
@@ -228,7 +235,7 @@ func (wm *WorkspaceManager) scheduleIdleGuarded(fn func() bool, nodes ...*paneNo
228235 }
229236 }
230237 return fn()
231- })
238+ }))
232239 if handle != 0 {
233240 wm.registerIdleHandle(handle, guards...)
234241 }
@@ -302,7 +309,7 @@ func (wm *WorkspaceManager) cancelIdleHandle(handle uintptr) {
302309 return
303310 }
304311 wm.releaseIdleHandle(handle)
305- webkit.IdleRemove(handle)
312+ glib.SourceRemove(uint(handle))
306313 }
307314
308315 func (wm *WorkspaceManager) cancelIdleHandles(node *paneNode) {
@@ -329,7 +336,7 @@ func formatPaneInfo(node *paneNode) string {
329336
330337 var info string
331338 if node.isLeaf {
332- info = fmt.Sprintf("leaf(container=%#x", node.container)
339+ info = fmt.Sprintf("leaf(container=%p", node.container)
333340 if node.pane != nil && node.pane.webView != nil {
334341 info += fmt.Sprintf(" webview=%s", node.pane.webView.ID())
335342 }
@@ -338,10 +345,10 @@ func formatPaneInfo(node *paneNode) string {
338345 }
339346 info += ")"
340347 } else if node.isStacked {
341- info = fmt.Sprintf("stack(panes=%d active=%d container=%#x)",
348+ info = fmt.Sprintf("stack(panes=%d active=%d container=%p)",
342349 len(node.stackedPanes), node.activeStackIndex, node.container)
343350 } else {
344- info = fmt.Sprintf("branch(container=%#x orientation=%v)",
351+ info = fmt.Sprintf("branch(container=%p orientation=%v)",
345352 node.container, node.orientation)
346353 }
347354
@@ -6,6 +6,7 @@ import (
6 "log"6 "log"
7 7
8 "github.com/bnema/dumber/pkg/webkit"8 "github.com/bnema/dumber/pkg/webkit"
9+ "github.com/diamondburned/gotk4/pkg/glib/v2"
9 "github.com/diamondburned/gotk4/pkg/gtk/v4"10 "github.com/diamondburned/gotk4/pkg/gtk/v4"
10 )11 )
11 12
@@ -98,10 +99,10 @@ func (wm *WorkspaceManager) setStackWrapper(node *paneNode, widget gtk.Widgetter
98 99
99 // PaneBorderContext holds the context for applying borders to any pane type100 // PaneBorderContext holds the context for applying borders to any pane type
100 type PaneBorderContext struct {101 type PaneBorderContext struct {
101- webViewWidget uintptr // The WebView's native widget (for margin)102+ webViewWidget gtk.Widgetter // The WebView's native widget (for margin)
102- borderContainer uintptr // The container that gets background color103+ borderContainer gtk.Widgetter // The container that gets background color
103- cssClasses []string // Additional CSS classes to apply104+ cssClasses []string // Additional CSS classes to apply
104- paneType string // Description for debugging105+ paneType string // Description for debugging
105 }106 }
106 107
107 // determineBorderContext analyzes a pane node and determines the correct border context108 // determineBorderContext analyzes a pane node and determines the correct border context
@@ -155,18 +156,21 @@ func (wm *WorkspaceManager) applyActivePaneBorder(ctx *PaneBorderContext) {
155 }156 }
156 157
157 // Apply margin to WebView widget (creates space for border)158 // Apply margin to WebView widget (creates space for border)
158- if ctx.webViewWidget != 0 && webkit.WidgetIsValid(ctx.webViewWidget) {159+ if ctx.webViewWidget != nil {
159- webkit.WidgetSetMargin(ctx.webViewWidget, 2)160+ ctx.webViewWidget.SetMarginTop(2)
161+ ctx.webViewWidget.SetMarginBottom(2)
162+ ctx.webViewWidget.SetMarginStart(2)
163+ ctx.webViewWidget.SetMarginEnd(2)
160 }164 }
161 165
162 // Apply CSS classes to border container166 // Apply CSS classes to border container
163- if ctx.borderContainer != 0 && webkit.WidgetIsValid(ctx.borderContainer) {167+ if ctx.borderContainer != nil {
164 for _, class := range ctx.cssClasses {168 for _, class := range ctx.cssClasses {
165- webkit.WidgetAddCSSClass(ctx.borderContainer, class)169+ ctx.borderContainer.AddCSSClass(class)
166 }170 }
167 }171 }
168 172
169- log.Printf("[workspace] Applied active border: type=%s webView=%#x container=%#x",173+ log.Printf("[workspace] Applied active border: type=%s webView=%p container=%p",
170 ctx.paneType, ctx.webViewWidget, ctx.borderContainer)174 ctx.paneType, ctx.webViewWidget, ctx.borderContainer)
171 }175 }
172 176
@@ -182,26 +186,29 @@ func (wm *WorkspaceManager) removeActivePaneBorder(node *paneNode) {
182 }186 }
183 187
184 // Remove margin from WebView widget188 // Remove margin from WebView widget
185- if ctx.webViewWidget != 0 && webkit.WidgetIsValid(ctx.webViewWidget) {189+ if ctx.webViewWidget != nil {
186- webkit.WidgetSetMargin(ctx.webViewWidget, 0)190+ ctx.webViewWidget.SetMarginTop(0)
191+ ctx.webViewWidget.SetMarginBottom(0)
192+ ctx.webViewWidget.SetMarginStart(0)
193+ ctx.webViewWidget.SetMarginEnd(0)
187 }194 }
188 195
189 // Remove CSS classes from border container196 // Remove CSS classes from border container
190- if ctx.borderContainer != 0 && webkit.WidgetIsValid(ctx.borderContainer) {197+ if ctx.borderContainer != nil {
191 for _, class := range ctx.cssClasses {198 for _, class := range ctx.cssClasses {
192- webkit.WidgetRemoveCSSClass(ctx.borderContainer, class)199+ ctx.borderContainer.RemoveCSSClass(class)
193 }200 }
194 }201 }
195 202
196- log.Printf("[workspace] Removed active border: type=%s webView=%#x container=%#x",203+ log.Printf("[workspace] Removed active border: type=%s webView=%p container=%p",
197 ctx.paneType, ctx.webViewWidget, ctx.borderContainer)204 ctx.paneType, ctx.webViewWidget, ctx.borderContainer)
198 }205 }
199 206
200 // Widget cleanup utilities207 // Widget cleanup utilities
201 208
202 // cleanupWidget safely invalidates and cleans up a widget209 // cleanupWidget safely invalidates and cleans up a widget
203-func (wm *WorkspaceManager) cleanupWidget(ptr uintptr) {210+func (wm *WorkspaceManager) cleanupWidget(widget gtk.Widgetter) {
204- if ptr == 0 {211+ if widget == nil {
205 return212 return
206 }213 }
207 214
@@ -217,7 +224,7 @@ func (wm *WorkspaceManager) scheduleIdleGuarded(fn func() bool, nodes ...*paneNo
217 }224 }
218 guards := uniquePaneNodes(nodes...)225 guards := uniquePaneNodes(nodes...)
219 var handle uintptr226 var handle uintptr
220- handle = webkit.IdleAdd(func() bool {227+ handle = uintptr(glib.IdleAdd(func() bool {
221 defer wm.releaseIdleHandle(handle)228 defer wm.releaseIdleHandle(handle)
222 for _, node := range guards {229 for _, node := range guards {
223 if node == nil {230 if node == nil {
@@ -228,7 +235,7 @@ func (wm *WorkspaceManager) scheduleIdleGuarded(fn func() bool, nodes ...*paneNo
228 }235 }
229 }236 }
230 return fn()237 return fn()
231- })238+ }))
232 if handle != 0 {239 if handle != 0 {
233 wm.registerIdleHandle(handle, guards...)240 wm.registerIdleHandle(handle, guards...)
234 }241 }
@@ -302,7 +309,7 @@ func (wm *WorkspaceManager) cancelIdleHandle(handle uintptr) {
302 return309 return
303 }310 }
304 wm.releaseIdleHandle(handle)311 wm.releaseIdleHandle(handle)
305- webkit.IdleRemove(handle)312+ glib.SourceRemove(uint(handle))
306 }313 }
307 314
308 func (wm *WorkspaceManager) cancelIdleHandles(node *paneNode) {315 func (wm *WorkspaceManager) cancelIdleHandles(node *paneNode) {
@@ -329,7 +336,7 @@ func formatPaneInfo(node *paneNode) string {
329 336
330 var info string337 var info string
331 if node.isLeaf {338 if node.isLeaf {
332- info = fmt.Sprintf("leaf(container=%#x", node.container)339+ info = fmt.Sprintf("leaf(container=%p", node.container)
333 if node.pane != nil && node.pane.webView != nil {340 if node.pane != nil && node.pane.webView != nil {
334 info += fmt.Sprintf(" webview=%s", node.pane.webView.ID())341 info += fmt.Sprintf(" webview=%s", node.pane.webView.ID())
335 }342 }
@@ -338,10 +345,10 @@ func formatPaneInfo(node *paneNode) string {
338 }345 }
339 info += ")"346 info += ")"
340 } else if node.isStacked {347 } else if node.isStacked {
341- info = fmt.Sprintf("stack(panes=%d active=%d container=%#x)",348+ info = fmt.Sprintf("stack(panes=%d active=%d container=%p)",
342 len(node.stackedPanes), node.activeStackIndex, node.container)349 len(node.stackedPanes), node.activeStackIndex, node.container)
343 } else {350 } else {
344- info = fmt.Sprintf("branch(container=%#x orientation=%v)",351+ info = fmt.Sprintf("branch(container=%p orientation=%v)",
345 node.container, node.orientation)352 node.container, node.orientation)
346 }353 }
347 354

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