gcla / gowid

Compositional widgets for terminal user interfaces, written in Go, inspired by urwid.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Jumping cursor on Windows

r-smith opened this issue · comments

When a text input box has focus with a blinking cursor, moving your mouse pointer across the console window causes the cursor to very rapidly jump back and forth between the top left corner and the cursor position in the text box. I can upload an animated gif if that helps explain it. I've only seen the issue on Windows, and only on edit-type widgets that have focus and a blinking cursor.

It looks like gowid triggers a redraw every time the mouse coordinates change. I've come up with a way to stop the cursor jumping, but I have no idea if it's right way to approach it. Here's what I have -

canvas.go - Windows cursor jump fix attempt

func Draw(canvas IDrawCanvas, mode IColorMode, screen tcell.Screen) {
	// cpos := CanvasPos{X: -1, Y: -1}
	// if canvas.CursorEnabled() {
	// 	cpos = canvas.CursorCoords()
	// }

	//screen.ShowCursor(-1, -1)

	if canvas.CursorEnabled() {
		cpos := canvas.CursorCoords()
		screen.ShowCursor(cpos.X, cpos.Y)

	} else {
		screen.HideCursor()
	}

	for y := 0; y < canvas.BoxRows(); y++ {
		line := canvas.Line(y, LineCopy{})
		vline := line.Line
		for x := 0; x < len(vline); {
			c := vline[x]
			f, b, s := c.ForegroundColor(), c.BackgroundColor(), c.Style()
			st := MakeCellStyle(f, b, s)
			screen.SetContent(x, y, c.Rune(), nil, st)
			x += runewidth.RuneWidth(c.Rune())

			// if x == cpos.X && y == cpos.Y {
			// 	screen.ShowCursor(x, y)
			// }
		}
	}
}

Hi Ryan - thanks, I like it! I have just one suggestion - could you check (cpos.X, cpos.Y) are within the bounds of the canvas, (canvas.BoxColumns(), canvas.BoxRows()) before calling ShowCursor()? I suppose then if you didn't call ShowCursor(), call HideCursor(). I tried your code and it works for me :-) If you can send a PR I'll merge it right in.

I also looked at tcell's console_win.go:doCursor() function - in there is a call to s.setCursorPos(0, 0) before s.hideCursor(), and I'm not sure what purpose it serves. If I comment that out, it also eliminates the flicker of the cursor hopping to the top left edge. I'll make a PR for tcell too.

Still, even if the flicker can be eliminated in tcell, I'd like to merge your modification.

The author of tcell merged this, so I'll make gowid depend on this newer version of tcell.