Skip to content

Commit 1c23430

Browse files
committed
Move all blink handling into Renderer
1 parent 4600c47 commit 1c23430

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+924
-1356
lines changed

.github/actions/spelling/expect/expect.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1765,6 +1765,7 @@ UINTs
17651765
uld
17661766
uldash
17671767
uldb
1768+
ULONGLONG
17681769
ulwave
17691770
Unadvise
17701771
unattend

src/buffer/out/cursor.cpp

Lines changed: 92 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -13,214 +13,157 @@
1313
// - ulSize - The height of the cursor within this buffer
1414
Cursor::Cursor(const ULONG ulSize, TextBuffer& parentBuffer) noexcept :
1515
_parentBuffer{ parentBuffer },
16-
_fIsVisible(true),
17-
_fIsOn(true),
18-
_fIsDouble(false),
19-
_fBlinkingAllowed(true),
20-
_fDelay(false),
21-
_fIsConversionArea(false),
22-
_fDelayedEolWrap(false),
23-
_fDeferCursorRedraw(false),
24-
_fHaveDeferredCursorRedraw(false),
25-
_ulSize(ulSize),
26-
_cursorType(CursorType::Legacy)
16+
_ulSize(ulSize)
2717
{
2818
}
2919

30-
Cursor::~Cursor() = default;
31-
3220
til::point Cursor::GetPosition() const noexcept
3321
{
3422
return _cPosition;
3523
}
3624

37-
bool Cursor::IsVisible() const noexcept
25+
uint64_t Cursor::GetLastMutationId() const noexcept
3826
{
39-
return _fIsVisible;
27+
return _mutationId;
4028
}
4129

42-
bool Cursor::IsOn() const noexcept
30+
bool Cursor::IsVisible() const noexcept
4331
{
44-
return _fIsOn;
32+
return _isVisible;
4533
}
4634

47-
bool Cursor::IsBlinkingAllowed() const noexcept
35+
bool Cursor::IsBlinking() const noexcept
4836
{
49-
return _fBlinkingAllowed;
37+
return _isBlinking;
5038
}
5139

5240
bool Cursor::IsDouble() const noexcept
5341
{
5442
return _fIsDouble;
5543
}
5644

57-
bool Cursor::IsConversionArea() const noexcept
58-
{
59-
return _fIsConversionArea;
60-
}
61-
62-
bool Cursor::GetDelay() const noexcept
63-
{
64-
return _fDelay;
65-
}
66-
6745
ULONG Cursor::GetSize() const noexcept
6846
{
6947
return _ulSize;
7048
}
7149

72-
void Cursor::SetIsVisible(const bool fIsVisible) noexcept
73-
{
74-
_fIsVisible = fIsVisible;
75-
_RedrawCursor();
76-
}
77-
78-
void Cursor::SetIsOn(const bool fIsOn) noexcept
50+
void Cursor::SetIsVisible(bool enable)
7951
{
80-
_fIsOn = fIsOn;
81-
_RedrawCursorAlways();
52+
if (_isVisible != enable)
53+
{
54+
_isVisible = enable;
55+
_redrawIfVisible();
56+
}
8257
}
8358

84-
void Cursor::SetBlinkingAllowed(const bool fBlinkingAllowed) noexcept
59+
void Cursor::SetIsBlinking(bool enable)
8560
{
86-
_fBlinkingAllowed = fBlinkingAllowed;
87-
// GH#2642 - From what we've gathered from other terminals, when blinking is
88-
// disabled, the cursor should remain On always, and have the visibility
89-
// controlled by the IsVisible property. So when you do a printf "\e[?12l"
90-
// to disable blinking, the cursor stays stuck On. At this point, only the
91-
// cursor visibility property controls whether the user can see it or not.
92-
// (Yes, the cursor can be On and NOT Visible)
93-
_fIsOn = true;
94-
_RedrawCursorAlways();
61+
if (_isBlinking != enable)
62+
{
63+
_isBlinking = enable;
64+
_redrawIfVisible();
65+
}
9566
}
9667

9768
void Cursor::SetIsDouble(const bool fIsDouble) noexcept
9869
{
99-
_fIsDouble = fIsDouble;
100-
_RedrawCursor();
101-
}
102-
103-
void Cursor::SetIsConversionArea(const bool fIsConversionArea) noexcept
104-
{
105-
// Functionally the same as "Hide cursor"
106-
// Never called with TRUE, it's only used in the creation of a
107-
// ConversionAreaInfo, and never changed after that.
108-
_fIsConversionArea = fIsConversionArea;
109-
_RedrawCursorAlways();
110-
}
111-
112-
void Cursor::SetDelay(const bool fDelay) noexcept
113-
{
114-
_fDelay = fDelay;
70+
if (_fIsDouble != fIsDouble)
71+
{
72+
_fIsDouble = fIsDouble;
73+
_redrawIfVisible();
74+
}
11575
}
11676

11777
void Cursor::SetSize(const ULONG ulSize) noexcept
11878
{
119-
_ulSize = ulSize;
120-
_RedrawCursor();
79+
if (_ulSize != ulSize)
80+
{
81+
_ulSize = ulSize;
82+
_redrawIfVisible();
83+
}
12184
}
12285

12386
void Cursor::SetStyle(const ULONG ulSize, const CursorType type) noexcept
12487
{
125-
_ulSize = ulSize;
126-
_cursorType = type;
127-
128-
_RedrawCursor();
129-
}
130-
131-
// Routine Description:
132-
// - Sends a redraw message to the renderer only if the cursor is currently on.
133-
// - NOTE: For use with most methods in this class.
134-
// Arguments:
135-
// - <none>
136-
// Return Value:
137-
// - <none>
138-
void Cursor::_RedrawCursor() noexcept
139-
{
140-
// Only trigger the redraw if we're on.
141-
// Don't draw the cursor if this was triggered from a conversion area.
142-
// (Conversion areas have cursors to mark the insertion point internally, but the user's actual cursor is the one on the primary screen buffer.)
143-
if (IsOn() && !IsConversionArea())
88+
if (_ulSize != ulSize || _cursorType != type)
14489
{
145-
if (_fDeferCursorRedraw)
146-
{
147-
_fHaveDeferredCursorRedraw = true;
148-
}
149-
else
150-
{
151-
_RedrawCursorAlways();
152-
}
90+
_ulSize = ulSize;
91+
_cursorType = type;
92+
_redrawIfVisible();
15393
}
15494
}
15595

156-
// Routine Description:
157-
// - Sends a redraw message to the renderer no matter what.
158-
// - NOTE: For use with the method that turns the cursor on and off to force a refresh
159-
// and clear the ON cursor from the screen. Not for use with other methods.
160-
// They should use the other method so refreshes are suppressed while the cursor is off.
161-
// Arguments:
162-
// - <none>
163-
// Return Value:
164-
// - <none>
165-
void Cursor::_RedrawCursorAlways() noexcept
166-
{
167-
_parentBuffer.NotifyPaintFrame();
168-
}
169-
17096
void Cursor::SetPosition(const til::point cPosition) noexcept
17197
{
172-
_RedrawCursor();
173-
_cPosition = cPosition;
174-
_RedrawCursor();
98+
// The VT code assumes that moving the cursor implicitly resets the delayed EOL wrap,
99+
// so we call ResetDelayEOLWrap() independent of _cPosition != cPosition.
100+
// You can see the effect of this with "`e[1;9999Ha`e[1;9999Hb", which should print just "b".
175101
ResetDelayEOLWrap();
102+
if (_cPosition != cPosition)
103+
{
104+
_cPosition = cPosition;
105+
_redrawIfVisible();
106+
}
176107
}
177108

178109
void Cursor::SetXPosition(const til::CoordType NewX) noexcept
179110
{
180-
_RedrawCursor();
181-
_cPosition.x = NewX;
182-
_RedrawCursor();
183111
ResetDelayEOLWrap();
112+
if (_cPosition.x != NewX)
113+
{
114+
_cPosition.x = NewX;
115+
_redrawIfVisible();
116+
}
184117
}
185118

186119
void Cursor::SetYPosition(const til::CoordType NewY) noexcept
187120
{
188-
_RedrawCursor();
189-
_cPosition.y = NewY;
190-
_RedrawCursor();
191121
ResetDelayEOLWrap();
122+
if (_cPosition.y != NewY)
123+
{
124+
_cPosition.y = NewY;
125+
_redrawIfVisible();
126+
}
192127
}
193128

194129
void Cursor::IncrementXPosition(const til::CoordType DeltaX) noexcept
195130
{
196-
_RedrawCursor();
197-
_cPosition.x += DeltaX;
198-
_RedrawCursor();
199131
ResetDelayEOLWrap();
132+
if (DeltaX != 0)
133+
{
134+
_cPosition.x = _cPosition.x + DeltaX;
135+
_redrawIfVisible();
136+
}
200137
}
201138

202139
void Cursor::IncrementYPosition(const til::CoordType DeltaY) noexcept
203140
{
204-
_RedrawCursor();
205-
_cPosition.y += DeltaY;
206-
_RedrawCursor();
207141
ResetDelayEOLWrap();
142+
if (DeltaY != 0)
143+
{
144+
_cPosition.y = _cPosition.y + DeltaY;
145+
_redrawIfVisible();
146+
}
208147
}
209148

210149
void Cursor::DecrementXPosition(const til::CoordType DeltaX) noexcept
211150
{
212-
_RedrawCursor();
213-
_cPosition.x -= DeltaX;
214-
_RedrawCursor();
215151
ResetDelayEOLWrap();
152+
if (DeltaX != 0)
153+
{
154+
_cPosition.x = _cPosition.x - DeltaX;
155+
_redrawIfVisible();
156+
}
216157
}
217158

218159
void Cursor::DecrementYPosition(const til::CoordType DeltaY) noexcept
219160
{
220-
_RedrawCursor();
221-
_cPosition.y -= DeltaY;
222-
_RedrawCursor();
223161
ResetDelayEOLWrap();
162+
if (DeltaY != 0)
163+
{
164+
_cPosition.y = _cPosition.y - DeltaY;
165+
_redrawIfVisible();
166+
}
224167
}
225168

226169
///////////////////////////////////////////////////////////////////////////////
@@ -233,78 +176,53 @@ void Cursor::DecrementYPosition(const til::CoordType DeltaY) noexcept
233176
// - OtherCursor - The cursor to copy properties from
234177
// Return Value:
235178
// - <none>
236-
void Cursor::CopyProperties(const Cursor& OtherCursor) noexcept
179+
void Cursor::CopyProperties(const Cursor& other) noexcept
237180
{
238-
// We shouldn't copy the position as it will be already rearranged by the resize operation.
239-
//_cPosition = pOtherCursor->_cPosition;
240-
241-
_fIsVisible = OtherCursor._fIsVisible;
242-
_fIsOn = OtherCursor._fIsOn;
243-
_fIsDouble = OtherCursor._fIsDouble;
244-
_fBlinkingAllowed = OtherCursor._fBlinkingAllowed;
245-
_fDelay = OtherCursor._fDelay;
246-
_fIsConversionArea = OtherCursor._fIsConversionArea;
247-
248-
// A resize operation should invalidate the delayed end of line status, so do not copy.
249-
//_fDelayedEolWrap = OtherCursor._fDelayedEolWrap;
250-
//_coordDelayedAt = OtherCursor._coordDelayedAt;
251-
252-
_fDeferCursorRedraw = OtherCursor._fDeferCursorRedraw;
253-
_fHaveDeferredCursorRedraw = OtherCursor._fHaveDeferredCursorRedraw;
254-
255-
// Size will be handled separately in the resize operation.
256-
//_ulSize = OtherCursor._ulSize;
257-
_cursorType = OtherCursor._cursorType;
181+
_cPosition = other._cPosition;
182+
_coordDelayedAt = other._coordDelayedAt;
183+
_ulSize = other._ulSize;
184+
_cursorType = other._cursorType;
185+
_isVisible = other._isVisible;
186+
_isBlinking = other._isBlinking;
187+
_fIsDouble = other._fIsDouble;
258188
}
259189

260190
void Cursor::DelayEOLWrap() noexcept
261191
{
262192
_coordDelayedAt = _cPosition;
263-
_fDelayedEolWrap = true;
264193
}
265194

266195
void Cursor::ResetDelayEOLWrap() noexcept
267196
{
268-
_coordDelayedAt = {};
269-
_fDelayedEolWrap = false;
197+
_coordDelayedAt.reset();
270198
}
271199

272-
til::point Cursor::GetDelayedAtPosition() const noexcept
200+
const std::optional<til::point>& Cursor::GetDelayEOLWrap() const noexcept
273201
{
274202
return _coordDelayedAt;
275203
}
276204

277-
bool Cursor::IsDelayedEOLWrap() const noexcept
205+
CursorType Cursor::GetType() const noexcept
278206
{
279-
return _fDelayedEolWrap;
280-
}
281-
282-
void Cursor::StartDeferDrawing() noexcept
283-
{
284-
_fDeferCursorRedraw = true;
207+
return _cursorType;
285208
}
286209

287-
bool Cursor::IsDeferDrawing() noexcept
210+
void Cursor::SetType(const CursorType type) noexcept
288211
{
289-
return _fDeferCursorRedraw;
212+
_cursorType = type;
290213
}
291214

292-
void Cursor::EndDeferDrawing() noexcept
215+
void Cursor::_redrawIfVisible() noexcept
293216
{
294-
if (_fHaveDeferredCursorRedraw)
217+
_mutationId++;
218+
if (_isVisible)
295219
{
296-
_RedrawCursorAlways();
220+
_parentBuffer.NotifyPaintFrame();
297221
}
298-
299-
_fDeferCursorRedraw = FALSE;
300222
}
301223

302-
const CursorType Cursor::GetType() const noexcept
224+
void Cursor::_redraw() noexcept
303225
{
304-
return _cursorType;
305-
}
306-
307-
void Cursor::SetType(const CursorType type) noexcept
308-
{
309-
_cursorType = type;
226+
_mutationId++;
227+
_parentBuffer.NotifyPaintFrame();
310228
}

0 commit comments

Comments
 (0)