1
0
mirror of https://github.com/gdamore/tcell.git synced 2025-04-24 13:48:51 +08:00

Implement focus events

This commit is contained in:
stk 2023-03-11 18:05:12 +01:00 committed by Garrett D'Amore
parent a92c043b0b
commit 85dc29bf8a
3 changed files with 84 additions and 1 deletions

View File

@ -135,6 +135,7 @@ func main() {
btnfmt := "Buttons: %s" btnfmt := "Buttons: %s"
keyfmt := "Keys: %s" keyfmt := "Keys: %s"
pastefmt := "Paste: [%d] %s" pastefmt := "Paste: [%d] %s"
focusfmt := "Focus: %s"
white := tcell.StyleDefault. white := tcell.StyleDefault.
Foreground(tcell.ColorMidnightBlue).Background(tcell.ColorLightCoral) Foreground(tcell.ColorMidnightBlue).Background(tcell.ColorLightCoral)
@ -148,9 +149,10 @@ func main() {
pstr := "" pstr := ""
ecnt := 0 ecnt := 0
pasting := false pasting := false
focus := true // assume we are focused when we start
for { for {
drawBox(s, 1, 1, 42, 7, white, ' ') drawBox(s, 1, 1, 42, 8, white, ' ')
emitStr(s, 2, 2, white, "Press ESC twice to exit, C to clear.") emitStr(s, 2, 2, white, "Press ESC twice to exit, C to clear.")
emitStr(s, 2, 3, white, fmt.Sprintf(posfmt, mx, my)) emitStr(s, 2, 3, white, fmt.Sprintf(posfmt, mx, my))
emitStr(s, 2, 4, white, fmt.Sprintf(btnfmt, bstr)) emitStr(s, 2, 4, white, fmt.Sprintf(btnfmt, bstr))
@ -162,6 +164,12 @@ func main() {
} }
emitStr(s, 2, 6, white, fmt.Sprintf(pastefmt, len(pstr), ps)) emitStr(s, 2, 6, white, fmt.Sprintf(pastefmt, len(pstr), ps))
fstr := "false"
if focus {
fstr = "true"
}
emitStr(s, 2, 7, white, fmt.Sprintf(focusfmt, fstr))
s.Show() s.Show()
bstr = "" bstr = ""
ev := s.PollEvent() ev := s.PollEvent()
@ -315,6 +323,8 @@ func main() {
lchar = ch lchar = ch
s.SetContent(w-1, h-1, 'M', nil, st) s.SetContent(w-1, h-1, 'M', nil, st)
mx, my = x, y mx, my = x, y
case *tcell.EventFocus:
focus = ev.Focused
default: default:
s.SetContent(w-1, h-1, 'X', nil, st) s.SetContent(w-1, h-1, 'X', nil, st)
} }

28
focus.go Normal file
View File

@ -0,0 +1,28 @@
// Copyright 2023 The TCell Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use file except in compliance with the License.
// You may obtain a copy of the license at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package tcell
// EventFocus is a focus event. It is sent when the terminal window (or tab)
// gets or loses focus.
type EventFocus struct {
*EventTime
// True if the window received focus, false if it lost focus
Focused bool
}
func NewEventFocus(focused bool) *EventFocus {
return &EventFocus{Focused: focused}
}

View File

@ -1043,6 +1043,14 @@ func (t *tScreen) enablePasting(on bool) {
} }
} }
func (t *tScreen) enableFocusReporting() {
t.TPuts("\x1b[?1004h")
}
func (t *tScreen) disableFocusReporting() {
t.TPuts("\x1b[?1004l")
}
func (t *tScreen) Size() (int, int) { func (t *tScreen) Size() (int, int) {
t.Lock() t.Lock()
w, h := t.w, t.h w, h := t.w, t.h
@ -1382,6 +1390,35 @@ func (t *tScreen) parseSgrMouse(buf *bytes.Buffer, evs *[]Event) (bool, bool) {
return true, false return true, false
} }
func (t *tScreen) parseFocus(buf *bytes.Buffer, evs *[]Event) (bool, bool) {
state := 0
b := buf.Bytes()
for i := range b {
switch state {
case 0:
if b[i] != '\x1b' {
return false, false
}
state = 1
case 1:
if b[i] != '[' {
return false, false
}
state = 2
case 2:
if b[i] != 'I' && b[i] != 'O' {
return false, false
}
*evs = append(*evs, NewEventFocus(b[i] == 'I'))
_, _ = buf.ReadByte()
_, _ = buf.ReadByte()
_, _ = buf.ReadByte()
return true, true
}
}
return true, false
}
// parseXtermMouse is like parseSgrMouse, but it parses a legacy // parseXtermMouse is like parseSgrMouse, but it parses a legacy
// X11 mouse record. // X11 mouse record.
func (t *tScreen) parseXtermMouse(buf *bytes.Buffer, evs *[]Event) (bool, bool) { func (t *tScreen) parseXtermMouse(buf *bytes.Buffer, evs *[]Event) (bool, bool) {
@ -1558,6 +1595,12 @@ func (t *tScreen) collectEventsFromInput(buf *bytes.Buffer, expire bool) []Event
partials++ partials++
} }
if part, comp := t.parseFocus(buf, &res); comp {
continue
} else if part {
partials++
}
// Only parse mouse records if this term claims to have // Only parse mouse records if this term claims to have
// mouse support // mouse support
@ -1806,6 +1849,7 @@ func (t *tScreen) engage() error {
t.stopQ = stopQ t.stopQ = stopQ
t.enableMouse(t.mouseFlags) t.enableMouse(t.mouseFlags)
t.enablePasting(t.pasteEnabled) t.enablePasting(t.pasteEnabled)
t.enableFocusReporting()
ti := t.ti ti := t.ti
t.TPuts(ti.EnterCA) t.TPuts(ti.EnterCA)
@ -1855,6 +1899,7 @@ func (t *tScreen) disengage() {
t.TPuts(ti.ExitKeypad) t.TPuts(ti.ExitKeypad)
t.enableMouse(0) t.enableMouse(0)
t.enablePasting(false) t.enablePasting(false)
t.disableFocusReporting()
_ = t.tty.Stop() _ = t.tty.Stop()
} }