move.go RawHistoryFolder
1package daemon
2
3import (
4 "reflect"
5
6 "github.com/bnema/vev/internal/domain"
7)
8
9// movePaneRequest identifies both lifecycles and both topology objects by
10// immutable identity. Session names are advisory; the ID and incarnation are
11// the commit-time authority.
12type movePaneRequest struct {
13 Follow bool
14 BeforeFollow func() error
15 AfterFollow func(*attachmentEffect)
16 Attachment *attachedClient
17 AttachmentCapability attachmentCapability
18 Source moveSessionLocator
19 SourceTabID domain.TabStableID
20 SourcePaneID domain.PaneStableID
21 Destination moveSessionLocator
22 DestinationTabID domain.TabStableID
23}
24
25type moveTabRequest struct {
26 Follow bool
27 BeforeFollow func() error
28 AfterFollow func(*attachmentEffect)
29 Attachment *attachedClient
30 AttachmentCapability attachmentCapability
31 Source moveSessionLocator
32 SourceTabID domain.TabStableID
33 Destination moveSessionLocator
34}
35
36func (d *Daemon) movePane(req movePaneRequest) error {
37 return d.executeMove(&movePaneTopology{req: req})
38}
39
40// moveSessionForLocatorLocked resolves only live sessions. The name is
41// intentionally ignored after the stable ID/incarnation pair is checked.
42func moveSessionForLocatorLocked(d *Daemon, locator moveSessionLocator) *session {
43 if d == nil {
44 return nil
45 }
46 sess := d.sessions[locator.ID]
47 if sess == nil || sess.incarnation != locator.Incarnation {
48 return nil
49 }
50 return sess
51}
52
53func moveSessionLocatorCurrentLocked(sess *session, locator moveSessionLocator) bool {
54 return sess != nil && sess.id == locator.ID && sess.incarnation == locator.Incarnation
55}
56
57func findMoveTabLocked(sess *session, stableID domain.TabStableID) *tab {
58 if sess == nil {
59 return nil
60 }
61 for _, tb := range sess.tabs {
62 if tb != nil && tb.stableID == string(stableID) {
63 return tb
64 }
65 }
66 return nil
67}
68
69func indexMoveTabLocked(sess *session, target *tab) int {
70 for i, tb := range sess.tabs {
71 if tb == target {
72 return i
73 }
74 }
75 return -1
76}
77
78func moveTabMemberLocked(sess *session, target *tab) bool {
79 return indexMoveTabLocked(sess, target) >= 0
80}
81
82func lockMoveTabs(a, b *tab) func() {
83 if a == nil && b == nil {
84 return func() {}
85 }
86 if a == nil {
87 b.mu.Lock()
88 return b.mu.Unlock
89 }
90 if b == nil {
91 a.mu.Lock()
92 return a.mu.Unlock
93 }
94 if a == b {
95 a.mu.Lock()
96 return a.mu.Unlock
97 }
98 first, second := a, b
99 if first.stableID > second.stableID ||
100 (first.stableID == second.stableID && reflect.ValueOf(first).Pointer() > reflect.ValueOf(second).Pointer()) {
101 first, second = second, first
102 }
103 first.mu.Lock()
104 second.mu.Lock()
105 return func() {
106 second.mu.Unlock()
107 first.mu.Unlock()
108 }
109}
110
111func lockMoveDispatch(a, b *session) func() {
112 if a == b {
113 a.dispatchMu.Lock()
114 return a.dispatchMu.Unlock
115 }
116 first, second := a, b
117 if first.id > second.id {
118 first, second = second, first
119 }
120 first.dispatchMu.Lock()
121 second.dispatchMu.Lock()
122 return func() {
123 second.dispatchMu.Unlock()
124 first.dispatchMu.Unlock()
125 }
126}