Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: x/sys/windows: console input event union member types #69965

Open
aymanbagabas opened this issue Oct 21, 2024 · 3 comments
Open

proposal: x/sys/windows: console input event union member types #69965

aymanbagabas opened this issue Oct 21, 2024 · 3 comments

Comments

@aymanbagabas
Copy link

aymanbagabas commented Oct 21, 2024

Proposal Details

On Windows, reading console events can be achieved by either using Console Virtual Terminal Sequences similar to Unix terminals, or by using the Windows Console API and Buffer Events.

The former only supports basic key/mouse events (no release or unambiguous keys). Because Windows Consoles are not traditional TTYs, and they don't support SIGWINCH signals, we cannot listen to window resize events without polling the console.

Thus, it's more beneficial to work with the latter API when dealing with terminals and consoles on Windows. Using the Console API, we can listen for window resize events, and mouse/keyboard release and unambiguous events (such as ctrl+i vs tab).

The Windows Console API defines input record events as a union type. And since Go doesn't support unions, we need a way to decode and access field members. The proposed change (CL 621496) is to use encoding/binary to decode the event into its respective type using member functions.

typedef struct _INPUT_RECORD {
  WORD  EventType;
  union {
    KEY_EVENT_RECORD          KeyEvent;
    MOUSE_EVENT_RECORD        MouseEvent;
    WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
    MENU_EVENT_RECORD         MenuEvent;
    FOCUS_EVENT_RECORD        FocusEvent;
  } Event;
} INPUT_RECORD;

Becomes

type InputRecord struct {
	EventType uint16
	_ [2]byte
	Event [16]byte
}

func (ir InputRecord) FocusEvent() FocusEventRecord {
	return FocusEventRecord{SetFocus: ir.Event[0] > 0}
}

func (ir InputRecord) KeyEvent() KeyEventRecord {
	return KeyEventRecord{
		KeyDown:         binary.LittleEndian.Uint32(ir.Event[0:4]) > 0,
		RepeatCount:     binary.LittleEndian.Uint16(ir.Event[4:6]),
		VirtualKeyCode:  binary.LittleEndian.Uint16(ir.Event[6:8]),
		VirtualScanCode: binary.LittleEndian.Uint16(ir.Event[8:10]),
		Char:            rune(binary.LittleEndian.Uint16(ir.Event[10:12])),
		ControlKeyState: binary.LittleEndian.Uint32(ir.Event[12:16]),
	}
}

func (ir InputRecord) MouseEvent() MouseEventRecord {
	return MouseEventRecord{
		MousePositon: Coord{
			X: int16(binary.LittleEndian.Uint16(ir.Event[0:2])),
			Y: int16(binary.LittleEndian.Uint16(ir.Event[2:4])),
		},
		ButtonState:     binary.LittleEndian.Uint32(ir.Event[4:8]),
		ControlKeyState: binary.LittleEndian.Uint32(ir.Event[8:12]),
		EventFlags:      binary.LittleEndian.Uint32(ir.Event[12:16]),
	}
}

func (ir InputRecord) WindowBufferSizeEvent() WindowBufferSizeRecord {
	return WindowBufferSizeRecord{
		Size: Coord{
			X: int16(binary.LittleEndian.Uint16(ir.Event[0:2])),
			Y: int16(binary.LittleEndian.Uint16(ir.Event[2:4])),
		},
	}
}

func (ir InputRecord) MenuEvent() MenuEventRecord {
	return MenuEventRecord{
		CommandID: binary.LittleEndian.Uint32(ir.Event[0:4]),
	}
}

Discussed in golang/sys#196
Related golang/sys#227
Related golang/sys#228

@ianlancetaylor
Copy link
Member

CC @golang/windows

@alexbrainman
Copy link
Member

Thank you @aymanbagabas ,

Related golang/sys#227
Related golang/sys#228

These are not a simple Windows API additions that usually include functions, structs and consts. These contain struct methods that do not exist in Windows API.

The CLs are pretty large too.

Do we want these changes added to golang.org/x/sys/windows package? Maybe they can go into different package? Do we want this API adjusted in any way?

Thank you.

Alex

@aymanbagabas
Copy link
Author

aymanbagabas commented Oct 22, 2024

Related golang/sys#227
Related golang/sys#228

These are not a simple Windows API additions that usually include functions, structs and consts. These contain struct methods that do not exist in Windows API.

The first one, golang/sys#227 (CL 621515), is a simple one that adds Windows API functions, structs, and consts. The second PR golang/sys#228 builds on the first and adds struct methods that match the union type field names in the API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Incoming
Development

No branches or pull requests

4 participants