Proposed Design for a modern Cursor system in v2 | Terminal.Gui v2 (original) (raw)

Important

This document is a work in progress and does not represent the final design or even the current implementation.

See end for list of issues this design addresses.

Tenets for Cursor Support (Unless you know better ones...)

  1. More GUI than Command Line. The concept of a cursor on the command line of a terminal is intrinsically tied to enabling the user to know where keyboard import is going to impact text editing. TUI apps have many more modalities than text editing where the keyboard is used (e.g. scrolling through a ColorPicker). Terminal.Gui's cursor system is biased towards the broader TUI experiences.
  2. Be Consistent With the User's Platform - Users get to choose the platform they run Terminal.Gui apps on and the cursor should behave in a way consistent with the terminal.

Lexicon & Taxonomy

Requirements

Design

View Focus Changes

It doesn't make sense the every View instance has it's own notion of MostFocused. The current implemention is overly complicated and fragile because the concept of "MostFocused" is handled by View. There can be only ONE "most focused" view in an application. MostFocused should be a property on Application.

MORE THOUGHT REQUIRED HERE - There be dragons given how Toplevel has OnEnter/OnLeave overrrides. The above needs more study, but is directioally correct.

View Cursor Changes

ConsoleDrivers

Application

Issues with Current Design

Driver.Row/Pos, which are changed via Move serves two purposes that confuse each other:

a) Where the next AddRune will put the next rune b) The current "Cursor Location"

If most TUI apps acted like a command line where the visible cursor was always visible, this might make sense. But the fact that only a very few View subclasses we've seen actually care to show the cursor illustrates a problem:

Any drawing causes the "Cursor Position" to be changed/lost. This means we have a ton of code that is constantly repositioning the cursor every MainLoop iteration.

The actual cursor position RARELY changes (relative to Mainloop.Iteration).

Derived from above, the current design means we need to call View.PositionCursor` every iteration. For some views this is a low-cost operation. For others it involves a lot of math.

This is just stupid.

Flicker

Related to the above, we need constantly Show/Hide the cursor every iteration. This causes ridiculous cursor flicker.

View.PositionCursor is poorly spec'd and confusing to implement correctly

Should a view call base.PositionCursor? If so, before or after doing stuff?

Setting cursor visibility in OnEnter actually makes no sense

First, leaving it up to views to do this is fragile.

Second, when a View gets focus is but one of many places where cursor visibilty should be updated.