mirror of https://github.com/liamg/aminal.git
mouse modes
This commit is contained in:
parent
f6df4d1931
commit
7c7a7e2bc7
|
@ -123,6 +123,7 @@ func (gui *GUI) Render() error {
|
|||
gui.window.SetKeyCallback(gui.key)
|
||||
gui.window.SetCharCallback(gui.char)
|
||||
gui.window.SetScrollCallback(gui.glfwScrollCallback)
|
||||
gui.window.SetMouseButtonCallback(gui.mouseButtonCallback)
|
||||
gui.window.SetRefreshCallback(func(w *glfw.Window) {
|
||||
select {
|
||||
case changeChan <- true:
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
package gui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-gl/glfw/v3.2/glfw"
|
||||
"gitlab.com/liamg/raft/terminal"
|
||||
)
|
||||
|
||||
func (gui *GUI) mouseButtonCallback(w *glfw.Window, button glfw.MouseButton, action glfw.Action, mod glfw.ModifierKey) {
|
||||
|
||||
// https://www.xfree86.org/4.8.0/ctlseqs.html
|
||||
|
||||
/*
|
||||
Parameters (such as pointer position and button number) for all mouse tracking escape sequences
|
||||
generated by xterm encode numeric parameters in a single character as value+32. For example,
|
||||
! specifies the value 1. The upper left character position on the terminal is denoted as 1,1.
|
||||
*/
|
||||
|
||||
switch gui.terminal.GetMouseMode() {
|
||||
case terminal.MouseModeNone:
|
||||
|
||||
// handle clicks locally
|
||||
|
||||
return
|
||||
case terminal.MouseModeX10: //X10 compatibility mode
|
||||
|
||||
/*
|
||||
X10 compatibility mode sends an escape sequence only on button press, encoding the location and the mouse button pressed.
|
||||
|
||||
It is enabled by specifying parameter 9 to DECSET.
|
||||
|
||||
On button press, xterm sends CSI M C b C x C y (6 characters).
|
||||
|
||||
C b is button−1.
|
||||
|
||||
C x and C y are the x and y coordinates of the mouse when the button was pressed.
|
||||
*/
|
||||
|
||||
if action == glfw.Press {
|
||||
b := rune(button & 0xff)
|
||||
x := rune((gui.terminal.ActiveBuffer().CursorColumn() + 31) & 0xff)
|
||||
y := rune((gui.terminal.ActiveBuffer().CursorLine() + 31) & 0xff)
|
||||
packet := fmt.Sprintf("\x1b[%cb%cx%cyM", b, x, y)
|
||||
gui.terminal.Write([]byte(packet))
|
||||
}
|
||||
case terminal.MouseModeVT200: // normal
|
||||
/*
|
||||
|
||||
Normal tracking mode sends an escape sequence on both button press and release.
|
||||
|
||||
Modifier key (shift, ctrl, meta) information is also sent.
|
||||
|
||||
It is enabled by specifying parameter 1000 to DECSET.
|
||||
|
||||
On button press or release, xterm sends CSI M C b C x C y .
|
||||
|
||||
The low two bits of C b encode button information: 0=MB1 pressed, 1=MB2 pressed, 2=MB3 pressed, 3=release.
|
||||
|
||||
The next three bits encode the modifiers which were down when the button was pressed and are added together: 4=Shift, 8=Meta, 16=Control.
|
||||
|
||||
Note however that the shift and control bits are normally unavailable because xterm uses the control modifier with mouse for popup menus,
|
||||
and the shift modifier is used in the default translations for button events. The Meta modifier recognized by xterm is the mod1 mask, and
|
||||
is not necessarily the "Meta" key (see xmodmap).
|
||||
|
||||
C x and C y are the x and y coordinates of the mouse event, encoded as in X10 mode.
|
||||
|
||||
Wheel mice may return buttons 4 and 5. Those buttons are represented by the same event codes as buttons 1 and 2 respectively, except that 64 is added to the event code. Release events for the wheel buttons are not reported.
|
||||
*/
|
||||
var b byte
|
||||
if action == glfw.Press {
|
||||
switch button {
|
||||
case glfw.MouseButton1:
|
||||
b = 0
|
||||
case glfw.MouseButton2:
|
||||
b = 1
|
||||
case glfw.MouseButton3:
|
||||
b = 2
|
||||
default:
|
||||
return
|
||||
}
|
||||
} else if action == glfw.Release {
|
||||
b = 3
|
||||
} else {
|
||||
return
|
||||
}
|
||||
if mod&glfw.ModShift > 0 {
|
||||
b |= 4
|
||||
}
|
||||
if mod&glfw.ModSuper > 0 {
|
||||
b |= 8
|
||||
}
|
||||
if mod&glfw.ModControl > 0 {
|
||||
b |= 16
|
||||
}
|
||||
x := rune((gui.terminal.ActiveBuffer().CursorColumn() + 31) & 0xff)
|
||||
y := rune((gui.terminal.ActiveBuffer().CursorLine() + 31) & 0xff)
|
||||
packet := fmt.Sprintf("\x1b[%cb%cx%cyM", b, x, y)
|
||||
gui.terminal.Write([]byte(packet))
|
||||
|
||||
case terminal.MouseModeVT200Highlight:
|
||||
/*
|
||||
Mouse highlight tracking notifies a program of a button press, receives a range of lines from the program, highlights the region covered by the mouse within that range until button release, and then sends the program the release coordinates. It is enabled by specifying parameter 1001 to DECSET. Highlighting is performed only for button 1, though other button events can be received. Warning: use of this mode requires a cooperating program or it will hang xterm. On button press, the same information as for normal tracking is generated; xterm then waits for the program to send mouse tracking information. All X events are ignored until the proper escape sequence is received from the pty: CSI P s ; P s ; P s ; P s ; P s T . The parameters are func, startx, starty, firstrow, and lastrow. func is non-zero to initiate highlight tracking and zero to abort. startx and starty give the starting x and y location for the highlighted region. The ending location tracks the mouse, but will never be above row firstrow and will always be above row lastrow. (The top of the screen is row 1.) When the button is released, xterm reports the ending position one of two ways: if the start and end coordinates are valid text locations: CSI t C x C y . If either coordinate is past the end of the line: CSI T C x C y C x C y C x C y . The parameters are startx, starty, endx, endy, mousex, and mousey. startx, starty, endx, and endy give the starting and ending character positions of the region. mousex and mousey give the location of the mouse at button up, which may not be over a character.
|
||||
*/
|
||||
panic("VT200 mouse highlight mode not supported")
|
||||
|
||||
case terminal.MouseModeButtonEvent:
|
||||
/*
|
||||
Button-event tracking is essentially the same as normal tracking, but xterm also reports button-motion events. Motion events are reported only if the mouse pointer has moved to a different character cell. It is enabled by specifying parameter 1002 to DECSET. On button press or release, xterm sends the same codes used by normal tracking mode. On button-motion events, xterm adds 32 to the event code (the third character, C b ). The other bits of the event code specify button and modifier keys as in normal mode. For example, motion into cell x,y with button 1 down is reported as CSI M @ C x C y . ( @ = 32 + 0 (button 1) + 32 (motion indicator) ). Similarly, motion with button 3 down is reported as CSI M B C x C y . ( B = 32 + 2 (button 3) + 32 (motion indicator) ).
|
||||
*/
|
||||
panic("Mouse button event mode not supported")
|
||||
|
||||
case terminal.MouseModeAnyEvent:
|
||||
/*
|
||||
Any-event mode is the same as button-event mode, except that all motion events are reported, even if no mouse button is down. It is enabled by specifying 1003 to DECSET.
|
||||
|
||||
|
||||
*/
|
||||
panic("Mouse any event mode not supported")
|
||||
|
||||
default:
|
||||
panic("Unsupported mouse mode")
|
||||
}
|
||||
|
||||
}
|
|
@ -19,9 +19,34 @@ var csiSequenceMap = map[rune]csiSequenceHandler{
|
|||
}
|
||||
|
||||
func csiSetMode(modeStr string, enabled bool, terminal *Terminal) error {
|
||||
|
||||
/*
|
||||
Mouse support
|
||||
|
||||
#define SET_X10_MOUSE 9
|
||||
#define SET_VT200_MOUSE 1000
|
||||
#define SET_VT200_HIGHLIGHT_MOUSE 1001
|
||||
#define SET_BTN_EVENT_MOUSE 1002
|
||||
#define SET_ANY_EVENT_MOUSE 1003
|
||||
|
||||
#define SET_FOCUS_EVENT_MOUSE 1004
|
||||
|
||||
#define SET_EXT_MODE_MOUSE 1005
|
||||
#define SET_SGR_EXT_MODE_MOUSE 1006
|
||||
#define SET_URXVT_EXT_MODE_MOUSE 1015
|
||||
|
||||
#define SET_ALTERNATE_SCROLL 1007
|
||||
*/
|
||||
|
||||
switch modeStr {
|
||||
case "?1":
|
||||
terminal.modes.ApplicationCursorKeys = enabled
|
||||
case "?9":
|
||||
if enabled {
|
||||
terminal.SetMouseMode(MouseModeX10)
|
||||
} else {
|
||||
terminal.SetMouseMode(MouseModeNone)
|
||||
}
|
||||
case "?12", "?13":
|
||||
terminal.modes.BlinkingCursor = enabled
|
||||
case "?25":
|
||||
|
@ -32,6 +57,13 @@ func csiSetMode(modeStr string, enabled bool, terminal *Terminal) error {
|
|||
} else {
|
||||
terminal.UseMainBuffer()
|
||||
}
|
||||
case "?1000":
|
||||
// enable mouse tracking
|
||||
if enabled {
|
||||
terminal.SetMouseMode(MouseModeVT200)
|
||||
} else {
|
||||
terminal.SetMouseMode(MouseModeNone)
|
||||
}
|
||||
case "?1048":
|
||||
if enabled {
|
||||
terminal.ActiveBuffer().SaveCursor()
|
||||
|
|
|
@ -20,6 +20,17 @@ const (
|
|||
AltBuffer uint8 = 1
|
||||
)
|
||||
|
||||
type MouseMode uint
|
||||
|
||||
const (
|
||||
MouseModeNone MouseMode = iota
|
||||
MouseModeX10
|
||||
MouseModeVT200
|
||||
MouseModeVT200Highlight
|
||||
MouseModeButtonEvent
|
||||
MouseModeAnyEvent
|
||||
)
|
||||
|
||||
type Terminal struct {
|
||||
buffers []*buffer.Buffer
|
||||
activeBufferIndex uint8
|
||||
|
@ -33,6 +44,7 @@ type Terminal struct {
|
|||
pauseChan chan bool
|
||||
resumeChan chan bool
|
||||
modes Modes
|
||||
mouseMode MouseMode
|
||||
}
|
||||
|
||||
type Modes struct {
|
||||
|
@ -78,6 +90,14 @@ func New(pty *os.File, logger *zap.SugaredLogger, config config.Config) *Termina
|
|||
}
|
||||
}
|
||||
|
||||
func (terminal *Terminal) SetMouseMode(mode MouseMode) {
|
||||
terminal.mouseMode = mode
|
||||
}
|
||||
|
||||
func (terminal *Terminal) GetMouseMode() MouseMode {
|
||||
return terminal.mouseMode
|
||||
}
|
||||
|
||||
func (terminal *Terminal) UseMainBuffer() {
|
||||
terminal.activeBufferIndex = MainBuffer
|
||||
terminal.SetSize(uint(terminal.size.Width), uint(terminal.size.Height))
|
||||
|
|
Loading…
Reference in New Issue