1package core_test
2
3import (
4 "testing"
5
6 "github.com/bnema/neferwl/internal/ports"
7)
8
9// A window session renders the window alone, at its client size, from the
10// first frame and whatever workspace is shown; once the window leaves the
11// screen it is configured Captured, and the session ends when it goes.
12func TestCaptureWindowSession(t *testing.T) {
13 r := captureCore(t)
14 r.client <- ports.WindowMapped{ID: 1}
15 scene(t, r.scenes)
16 r.client <- ports.WindowMapped{ID: 2}
17 scene(t, r.scenes)
18 var ws []ports.WorkspaceInfo
19 for len(ws) < 2 {
20 ws = receive(t, r.workspaces).Outputs[0].Workspaces
21 }
22 r.client <- ports.CaptureSessionOpen{ID: 1, Window: 1}
23 st := r.state(t)
24 if !st.Active || !st.Hidden || st.Output != "OUT-1" || st.Rect.W <= 0 || st.Rect.H <= 0 || st.Rect.X != 0 || st.Rect.Y != 0 {
25 t.Fatalf("state %+v", st)
26 }
27 s := r.sceneWith(t, true)
28 if s.Capture.Window != 1 || s.Capture.Workspace != 0 || s.CaptureScene == nil {
29 t.Fatalf("capture %+v scene %v", s.Capture, s.CaptureScene)
30 }
31 c := s.CaptureScene
32 if c.OutputWidth != st.Rect.W || c.OutputHeight != st.Rect.H || len(c.Windows) != 1 || c.Windows[0].ID != 1 || c.Windows[0].Rect != (ports.Rect{W: st.Rect.W, H: st.Rect.H}) {
33 t.Fatalf("window scene %+v", c)
34 }
35
36 // Another workspace on screen: window 1 is hidden yet kept drawing.
37 r.client <- ports.WorkspaceActivate{IDs: []uint64{ws[1].ID}}
38 for {
39 v := r.configureOf(t, 1)
40 if !v.Visible {
41 if !v.Captured || v.Width != st.Rect.W {
42 t.Fatalf("hidden captured window %+v", v)
43 }
44 break
45 }
46 }
47 for {
48 if s = scene(t, r.scenes); s.Capture != nil && s.Capture.Window == 1 && s.CaptureScene != nil {
49 break
50 }
51 }
52
53 // The window goes: the session ends with window-gone.
54 r.client <- ports.WindowUnmapped{ID: 1}
55 for {
56 if st = r.state(t); st.Reason != ports.CaptureReasonNone {
57 break
58 }
59 }
60 if st.Reason != ports.CaptureReasonWindowGone {
61 t.Fatalf("end %+v", st)
62 }
63}
64
65// The indicator of a window session is a pill on its output, and the
66// window's outline while it is on screen.
67func TestCaptureWindowIndicator(t *testing.T) {
68 r := captureCore(t)
69 r.client <- ports.WindowMapped{ID: 1}
70 scene(t, r.scenes)
71 r.client <- ports.CaptureSessionOpen{ID: 1, Window: 1}
72 r.state(t)
73 r.client <- ports.CaptureFrameTaken{Session: 1, Window: 1}
74 for {
75 s := scene(t, r.scenes)
76 pill, border := false, false
77 for _, m := range s.CaptureIndicators {
78 pill = pill || m.Pill
79 border = border || !m.Pill
80 }
81 if pill && border {
82 return
83 }
84 }
85}
86
87// A captured window on a hidden workspace follows that workspace's layout:
88// when a sibling closes, the capture and its configure grow together.
89func TestCaptureWindowHiddenReflow(t *testing.T) {
90 r := captureCore(t)
91 r.client <- ports.WindowMapped{ID: 1}
92 scene(t, r.scenes)
93 r.client <- ports.WindowMapped{ID: 2}
94 scene(t, r.scenes)
95 var ws []ports.WorkspaceInfo
96 for len(ws) < 2 {
97 ws = receive(t, r.workspaces).Outputs[0].Workspaces
98 }
99 r.client <- ports.CaptureSessionOpen{ID: 1, Window: 1}
100 before := r.state(t)
101 r.client <- ports.WorkspaceActivate{IDs: []uint64{ws[1].ID}}
102 for {
103 if v := r.configureOf(t, 1); !v.Visible {
104 break
105 }
106 }
107 r.client <- ports.WindowUnmapped{ID: 2}
108 var after ports.CaptureSessionState
109 for {
110 if after = r.state(t); after.Rect != before.Rect {
111 break
112 }
113 }
114 for {
115 v := r.configureOf(t, 1)
116 if v.Width == after.Rect.W && v.Height == after.Rect.H {
117 if v.Visible || !v.Captured {
118 t.Fatalf("reflowed hidden window %+v", v)
119 }
120 return
121 }
122 }
123}