v0.33.2 57f21d6

webview_input_test.go RawHistoryFolder

1package cef
2
3import (
4	"context"
5	"testing"
6
7	"github.com/bnema/dumber/internal/application/port"
8	"github.com/bnema/dumber/internal/domain/entity"
9	cefmocks "github.com/bnema/purego-cef/cef/mocks"
10	"github.com/bnema/purego-cef2gtk"
11	"github.com/bnema/puregotk/v4/gdk"
12	"github.com/bnema/puregotk/v4/gtk"
13	"github.com/stretchr/testify/require"
14)
15
16func TestWebViewBridgeInputOptions_LeavesTargetSelectionToAdapter(t *testing.T) {
17	nativeWidget := &gtk.Widget{}
18	wv := &WebView{
19		nativeWidget: nativeWidget,
20		inputConfig: RuntimeInputConfig{
21			ScrollWheelMultiplier:              1.25,
22			ScrollPreciseMultiplier:            2.5,
23			ScrollHorizontalMultiplier:         0.75,
24			ScrollVerticalMultiplier:           1.5,
25			ScrollMaxDelta:                     120,
26			ScrollTouchpadInertia:              true,
27			ScrollWheelSmoothing:               true,
28			TouchpadNavigationEnabled:          true,
29			TouchpadNavigationMinDelta:         80,
30			TouchpadNavigationMaxVerticalRatio: 0.5,
31		},
32	}
33
34	opts := wv.bridgeInputOptions()
35
36	require.Zero(t, opts.Scale)
37	require.InDelta(t, 1.25, opts.Scroll.WheelMultiplier, 0.001)
38	require.InDelta(t, 2.5, opts.Scroll.PreciseMultiplier, 0.001)
39	require.InDelta(t, 0.75, opts.Scroll.HorizontalMultiplier, 0.001)
40	require.InDelta(t, 1.5, opts.Scroll.VerticalMultiplier, 0.001)
41	require.Equal(t, int32(120), opts.Scroll.MaxDelta)
42	require.True(t, opts.Scroll.TouchpadInertia)
43	require.True(t, opts.Scroll.WheelSmoothing)
44	require.NotNil(t, opts.OnMiddleClick)
45	require.NotNil(t, opts.OnScroll)
46	require.False(t, opts.NavigationSwipe.Enabled)
47	require.Zero(t, opts.NavigationSwipe.MinDelta)
48	require.Zero(t, opts.NavigationSwipe.MaxVerticalRatio)
49	require.Nil(t, opts.CanNavigateBack)
50	require.Nil(t, opts.CanNavigateForward)
51	require.Nil(t, opts.OnNavigateSwipe)
52	require.NotNil(t, opts.SelectionText)
53	require.NotNil(t, opts.OnClipboardShortcut)
54	require.Same(t, nativeWidget, wv.nativeWidget)
55}
56
57func TestWebViewHandleScrollInput_ForwardsOrdinaryHorizontalScroll(t *testing.T) {
58	wv := &WebView{
59		ctx: context.Background(),
60		inputConfig: RuntimeInputConfig{
61			TouchpadNavigationEnabled:          true,
62			TouchpadNavigationMinDelta:         200,
63			TouchpadNavigationMaxVerticalRatio: 0.5,
64		},
65		canGoBack: true,
66	}
67
68	// This verifies the bridge-level forwarding contract for ordinary scroll
69	// updates. The nil native widget leaves view width unknown, so local history
70	// gesture recognition fails closed and the event continues to CEF.
71	decision := wv.handleScrollInput(cef2gtk.ScrollEvent{
72		Phase:     cef2gtk.ScrollPhaseUpdate,
73		X:         500,
74		DX:        -240,
75		Unit:      gdk.ScrollUnitSurfaceValue,
76		UnitKnown: true,
77	})
78
79	require.Equal(t, cef2gtk.ScrollForwardToCEF, decision)
80}
81
82func TestWebViewHandleScrollInput_EmitsFinalGestureBeforeNavigation(t *testing.T) {
83	browser := cefmocks.NewMockBrowser(t)
84	events := make([]string, 0, 2)
85	browser.EXPECT().GoBack().Run(func() {
86		events = append(events, "go-back")
87	}).Once()
88
89	wv := &WebView{
90		ctx: context.Background(),
91		inputConfig: RuntimeInputConfig{
92			TouchpadNavigationEnabled:          true,
93			TouchpadNavigationMinDelta:         200,
94			TouchpadNavigationMaxVerticalRatio: 0.5,
95		},
96		canGoBack: true,
97		browser:   browser,
98		callbacks: &port.WebViewCallbacks{
99			OnTouchpadNavigationGesture: func(gesture entity.TouchpadNavigationGesture) {
100				if !gesture.Active && gesture.ThresholdReached {
101					events = append(events, "indicator-finished")
102				}
103			},
104		},
105	}
106
107	begin := wv.handleScrollInput(cef2gtk.ScrollEvent{
108		Phase:     cef2gtk.ScrollPhaseBegin,
109		X:         0,
110		Unit:      gdk.ScrollUnitSurfaceValue,
111		UnitKnown: true,
112	})
113	require.Equal(t, cef2gtk.ScrollForwardToCEF, begin)
114
115	// Avoid constructing GTK widgets in this package: the WebView integration
116	// only needs a known gesture width after begin records the starting edge.
117	wv.mu.Lock()
118	require.NotNil(t, wv.touchpadNavigation)
119	wv.touchpadNavigation.gestureViewWidth = 1000
120	wv.mu.Unlock()
121
122	update := wv.handleScrollInput(cef2gtk.ScrollEvent{
123		Phase:     cef2gtk.ScrollPhaseUpdate,
124		X:         0,
125		DX:        -240,
126		Unit:      gdk.ScrollUnitSurfaceValue,
127		UnitKnown: true,
128	})
129	require.Equal(t, cef2gtk.ScrollForwardToCEF, update)
130
131	end := wv.handleScrollInput(cef2gtk.ScrollEvent{
132		Phase:     cef2gtk.ScrollPhaseEnd,
133		X:         0,
134		Unit:      gdk.ScrollUnitSurfaceValue,
135		UnitKnown: true,
136	})
137	require.Equal(t, cef2gtk.ScrollForwardToCEF, end)
138	require.Equal(t, []string{"indicator-finished", "go-back"}, events)
139}

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