pointergrab.go RawHistoryFolder

1package core
2
3import (
4	"context"
5	"time"
6
7	"github.com/bnema/neferwl/internal/ports"
8)
9
10// pointerGrab is a compositor-owned pointer interaction started by cmd+button.
11// Clients get no pointer events while it runs. Implementations: borderResize
12// (border_resize.go); planned: column move within a workspace, and edge-hold
13// transfer of a dragged column to the next workspace or the adjacent monitor.
14type pointerGrab interface {
15	// valid reports whether the grab still applies to the current layout; the core aborts it otherwise.
16	valid() bool
17	button() uint32
18	motion(ctx context.Context, at time.Duration) error
19	release(ctx context.Context) error
20	cancel()        // Escape: restore the state from before the grab
21	cursor() string // CSS cursor name; "" = the client's cursor
22}
23
24func (c *Core) pointerBusy() bool { return c.drag != nil || c.pgrab != nil }
25
26func (c *Core) startPointerGrab(ctx context.Context, v ports.PointerButton) (bool, error) {
27	if c.synthetic || !v.Pressed || c.pointerBusy() || c.held() != 0 || c.grab != 0 || c.cmdMod == 0 || c.mods&c.cmdMod == 0 || c.keyboard.inhibited(c.keyboardFocus()) {
28		return false, nil
29	}
30	if v.Button == btnRight {
31		if i := c.screenAt(c.cursorX, c.cursorY); i >= 0 {
32			s := c.screens[i]
33			w := s.mon.Current()
34			lx, ly := int(c.cursorX)-s.x, int(c.cursorY)-s.y
35			if !s.mon.previewing() && !s.mon.ov.open && !w.pinned() && s.mon.frameHas(float64(lx), float64(ly)) {
36				if b, ok := w.borderAt(lx, ly, max(w.gap()/2, gapPad)); ok {
37					last := c.lastBorderClick
38					if last.ws == w && last.b.kind == b.kind && last.b.col == b.col && last.b.row == b.row && v.Time >= last.at && v.Time-last.at <= 400*time.Millisecond {
39						c.lastBorderClick.ws = nil
40						now := c.now()
41						shots := c.snapshot(now)
42						w.resetBorder(b)
43						c.transition(shots, now)
44						c.buttons[v.Button], c.swallow[v.Button] = true, true
45						return true, c.publish(ctx)
46					}
47					c.lastBorderClick.at, c.lastBorderClick.ws, c.lastBorderClick.b = v.Time, w, b
48					g := newBorderResize(c, s, w, b, v.Button)
49					return true, c.beginPointerGrab(ctx, g)
50				}
51			}
52		}
53	}
54	c.lastBorderClick.ws = nil
55	return c.startDrag(ctx, v)
56}
57
58func (c *Core) beginPointerGrab(ctx context.Context, g pointerGrab) error {
59	if err := c.dismissGrabs(ctx, 0); err != nil {
60		return err
61	}
62	c.pgrab = g
63	c.buttons[g.button()] = true
64	c.grab = 0
65	if c.pointer != 0 {
66		c.pointer = 0
67		if err := c.pointerFocus(ctx, ports.PointerFocus{}); err != nil {
68			return err
69		}
70	}
71	if err := c.command(ctx, ports.CursorOverride{Shape: g.cursor()}); err != nil {
72		return err
73	}
74	return c.publish(ctx)
75}
76
77func (c *Core) endPointerGrab(ctx context.Context) error {
78	g := c.pgrab
79	c.pgrab = nil
80	if err := c.command(ctx, ports.CursorOverride{}); err != nil {
81		return err
82	}
83	return g.release(ctx)
84}
85
86// abortPointerGrab keeps the current layout and swallows the held release.
87// The caller restores state first when this is an Escape cancellation.
88func (c *Core) abortPointerGrab(ctx context.Context) error {
89	if c.pgrab == nil {
90		return nil
91	}
92	c.swallow[c.pgrab.button()] = true
93	c.pgrab = nil
94	return c.command(ctx, ports.CursorOverride{})
95}

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 26

Tags 10

↑↓ moveenter openesc close