v0.30.0 eb3068f

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

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