mirror of
https://github.com/gdamore/tcell.git
synced 2025-04-24 13:48:51 +08:00
Implement Beep() API
Add a Beep() method to the Screen interface. On *nix systems, this writes the bell character (0x07) to the tty. On Windows, we call the MessageBeep syscall. Fixes: #2
This commit is contained in:
parent
96a065d8ff
commit
8ec73b6fa6
73
_demos/beep.go
Normal file
73
_demos/beep.go
Normal file
@ -0,0 +1,73 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
// beep makes a beep every second until you press ESC
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/gdamore/tcell"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tcell.SetEncodingFallback(tcell.EncodingFallbackASCII)
|
||||
s, e := tcell.NewScreen()
|
||||
if e != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", e)
|
||||
os.Exit(1)
|
||||
}
|
||||
if e = s.Init(); e != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", e)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
s.SetStyle(tcell.StyleDefault)
|
||||
s.Clear()
|
||||
|
||||
quit := make(chan struct{})
|
||||
go func() {
|
||||
for {
|
||||
ev := s.PollEvent()
|
||||
switch ev := ev.(type) {
|
||||
case *tcell.EventKey:
|
||||
switch ev.Key() {
|
||||
case tcell.KeyEscape, tcell.KeyEnter, tcell.KeyCtrlC:
|
||||
close(quit)
|
||||
return
|
||||
case tcell.KeyCtrlL:
|
||||
s.Sync()
|
||||
}
|
||||
case *tcell.EventResize:
|
||||
s.Sync()
|
||||
}
|
||||
}
|
||||
}()
|
||||
beep(s, quit)
|
||||
s.Fini()
|
||||
}
|
||||
|
||||
func beep(s tcell.Screen, quit <-chan struct{}) {
|
||||
t := time.NewTicker(time.Second)
|
||||
for {
|
||||
select {
|
||||
case <-quit:
|
||||
return
|
||||
case <-t.C:
|
||||
s.Beep()
|
||||
}
|
||||
}
|
||||
}
|
@ -90,10 +90,13 @@ var winColors = map[Color]Color{
|
||||
ColorWhite: ColorWhite,
|
||||
}
|
||||
|
||||
var k32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
var (
|
||||
k32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
u32 = syscall.NewLazyDLL("user32.dll")
|
||||
)
|
||||
|
||||
// We have to bring in the kernel32.dll directly, so we can get access to some
|
||||
// system calls that the core Go API lacks.
|
||||
// We have to bring in the kernel32 and user32 DLLs directly, so we can get
|
||||
// access to some system calls that the core Go API lacks.
|
||||
//
|
||||
// Note that Windows appends some functions with W to indicate that wide
|
||||
// characters (Unicode) are in use. The documentation refers to them
|
||||
@ -114,6 +117,7 @@ var (
|
||||
procSetConsoleWindowInfo = k32.NewProc("SetConsoleWindowInfo")
|
||||
procSetConsoleScreenBufferSize = k32.NewProc("SetConsoleScreenBufferSize")
|
||||
procSetConsoleTextAttribute = k32.NewProc("SetConsoleTextAttribute")
|
||||
procMessageBeep = u32.NewProc("MessageBeep")
|
||||
)
|
||||
|
||||
const (
|
||||
@ -1031,3 +1035,16 @@ func (s *cScreen) HasKey(k Key) bool {
|
||||
|
||||
return valid[k]
|
||||
}
|
||||
|
||||
func (s *cScreen) Beep() error {
|
||||
// A simple beep. If the sound card is not available, the sound is generated
|
||||
// using the speaker.
|
||||
//
|
||||
// Reference:
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebeep
|
||||
const simpleBeep = 0xffffffff
|
||||
if rv, _, err := procMessageBeep.Call(simpleBeep); rv == 0 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -193,6 +193,10 @@ type Screen interface {
|
||||
// menus, displayed hot-keys, etc. Note that KeyRune (literal
|
||||
// runes) is always true.
|
||||
HasKey(Key) bool
|
||||
|
||||
// Beep attempts to sound an OS-dependent audible alert and returns an error
|
||||
// when unsuccessful.
|
||||
Beep() error
|
||||
}
|
||||
|
||||
// NewScreen returns a default Screen suitable for the user's terminal
|
||||
|
41
sim_test.go
41
sim_test.go
@ -109,3 +109,44 @@ func TestResize(t *testing.T) {
|
||||
t.Errorf("Incorrect cell content after resize: %v", cell2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBeep(t *testing.T) {
|
||||
s := mkTestScreen(t, "")
|
||||
defer s.Fini()
|
||||
|
||||
b0, x0, y0 := s.GetContents()
|
||||
|
||||
if err := s.Beep(); err != nil {
|
||||
t.Errorf("could not beep: %v", err)
|
||||
}
|
||||
s.Show()
|
||||
|
||||
b1, x1, y1 := s.GetContents()
|
||||
if x0 != x1 {
|
||||
t.Fatalf("screen width changed unexpectedly from %d to %d", x0, x1)
|
||||
}
|
||||
if y0 != y1 {
|
||||
t.Fatalf("screen height changed unexpectedly from %d to %d", y0, y1)
|
||||
}
|
||||
if len(b0) != len(b1) {
|
||||
t.Fatalf("screen size changed unexpectedly (had %d cells, has %d cells)",
|
||||
len(b0), len(b1))
|
||||
}
|
||||
for i := 0; i < len(b0); i++ {
|
||||
cell0 := b0[i]
|
||||
cell1 := b1[i]
|
||||
if len(cell0.Runes) != len(cell1.Runes) {
|
||||
t.Errorf("incorrect cell content: had %d runes, has %d runes",
|
||||
len(cell0.Runes), len(cell1.Runes))
|
||||
continue
|
||||
}
|
||||
for j := 0; j < len(cell0.Runes); j++ {
|
||||
r0 := cell0.Runes[j]
|
||||
r1 := cell1.Runes[j]
|
||||
if r0 != r1 {
|
||||
t.Errorf("incorrect content: cell %d rune %d changed from %v to %v",
|
||||
i, j, r0, r1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -506,3 +506,7 @@ func (s *simscreen) Resize(int, int, int, int) {}
|
||||
func (s *simscreen) HasKey(Key) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *simscreen) Beep() error {
|
||||
return nil
|
||||
}
|
||||
|
@ -114,3 +114,8 @@ func (t *tScreen) getWinSize() (int, int, error) {
|
||||
}
|
||||
return int(dim[1]), int(dim[0]), nil
|
||||
}
|
||||
|
||||
func (t *tScreen) Beep() error {
|
||||
t.writeString(string(byte(7)))
|
||||
return nil
|
||||
}
|
||||
|
@ -135,3 +135,8 @@ func (t *tScreen) getWinSize() (int, int, error) {
|
||||
}
|
||||
return int(dim[1]), int(dim[0]), nil
|
||||
}
|
||||
|
||||
func (t *tScreen) Beep() error {
|
||||
t.writeString(string(byte(7)))
|
||||
return nil
|
||||
}
|
||||
|
@ -140,3 +140,8 @@ func (t *tScreen) getWinSize() (int, int, error) {
|
||||
}
|
||||
return cols, rows, nil
|
||||
}
|
||||
|
||||
func (t *tScreen) Beep() error {
|
||||
t.writeString(string(byte(7)))
|
||||
return nil
|
||||
}
|
||||
|
@ -30,3 +30,7 @@ func (t *tScreen) termioFini() {
|
||||
func (t *tScreen) getWinSize() (int, int, error) {
|
||||
return 0, 0, ErrNoScreen
|
||||
}
|
||||
|
||||
func (t *tScreen) Beep() error {
|
||||
return ErrNoScreen
|
||||
}
|
||||
|
@ -37,4 +37,8 @@ func (t *tScreen) getCharset() string {
|
||||
return "UTF-16LE"
|
||||
}
|
||||
|
||||
func (t *tScreen) Beep() error {
|
||||
return ErrNoScreen
|
||||
}
|
||||
|
||||
type termiosPrivate struct{}
|
||||
|
Loading…
x
Reference in New Issue
Block a user