Expand the agent's input dumping; change --showkey to --show-input

Details:

 * Rename --showkey to --show-input and dump everything *except* mouse
   input.

 * Add a mode, --show-input --with-mouse, that also dumps the mouse
   input.
This commit is contained in:
Ryan Prichard 2015-12-16 02:36:04 -06:00
parent c857ae1dea
commit d4b4cb6bcc
6 changed files with 250 additions and 53 deletions

203
src/agent/DebugShowInput.cc Executable file
View File

@ -0,0 +1,203 @@
// Copyright (c) 2015 Ryan Prichard
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
#include "DebugShowInput.h"
#include <windows.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <sstream>
#include "InputMap.h"
namespace {
struct Flag {
DWORD value;
const char *text;
};
static const Flag kButtonStates[] = {
{ FROM_LEFT_1ST_BUTTON_PRESSED, "1" },
{ FROM_LEFT_2ND_BUTTON_PRESSED, "2" },
{ FROM_LEFT_3RD_BUTTON_PRESSED, "3" },
{ FROM_LEFT_4TH_BUTTON_PRESSED, "4" },
{ RIGHTMOST_BUTTON_PRESSED, "R" },
};
static const Flag kControlKeyStates[] = {
{ CAPSLOCK_ON, "CapsLock" },
{ ENHANCED_KEY, "Enhanced" },
{ LEFT_ALT_PRESSED, "LAlt" },
{ LEFT_CTRL_PRESSED, "LCtrl" },
{ NUMLOCK_ON, "NumLock" },
{ RIGHT_ALT_PRESSED, "RAlt" },
{ RIGHT_CTRL_PRESSED, "RCtrl" },
{ SCROLLLOCK_ON, "ScrollLock" },
{ SHIFT_PRESSED, "Shift" },
};
static const Flag kMouseEventFlags[] = {
{ DOUBLE_CLICK, "Double" },
{ 8/*MOUSE_HWHEELED*/, "HWheel" },
{ MOUSE_MOVED, "Move" },
{ MOUSE_WHEELED, "Wheel" },
};
static void writeFlags(std::ostream &out, DWORD flags,
const char *remainderName,
const Flag *table, size_t tableSize,
char pre, char sep, char post) {
DWORD remaining = flags;
bool wroteSomething = false;
for (size_t i = 0; i < tableSize; ++i) {
const Flag &f = table[i];
if ((f.value & flags) == f.value) {
if (!wroteSomething && pre != '\0') {
out.put(pre);
} else if (wroteSomething && sep != '\0') {
out.put(sep);
}
out << f.text;
wroteSomething = true;
remaining &= ~f.value;
}
}
if (remaining != 0) {
if (!wroteSomething && pre != '\0') {
out.put(pre);
} else if (wroteSomething && sep != '\0') {
out.put(sep);
}
std::ios oldState(NULL);
oldState.copyfmt(out);
out << std::hex << remainderName << "(0x" << remaining << ")";
out.copyfmt(oldState);
wroteSomething = true;
}
if (wroteSomething && post != '\0') {
out.put(post);
}
}
template <size_t n>
static void writeFlags(std::ostream &out, DWORD flags,
const char *remainderName,
const Flag (&table)[n],
char pre, char sep, char post) {
writeFlags(out, flags, remainderName, table, n, pre, sep, post);
}
} // anonymous namespace
std::string controlKeyStatePrefix(DWORD controlKeyState) {
std::stringstream ss;
writeFlags(ss, controlKeyState,
"keyState", kControlKeyStates, '\0', '-', '-');
return ss.str();
}
std::string mouseEventToString(const MOUSE_EVENT_RECORD &mer) {
const uint16_t buttons = mer.dwButtonState & 0xFFFF;
const int16_t wheel = mer.dwButtonState >> 16;
std::stringstream ss;
ss << std::dec << "pos=" << mer.dwMousePosition.X << ','
<< mer.dwMousePosition.Y;
writeFlags(ss, mer.dwControlKeyState, "keyState", kControlKeyStates, ' ', ' ', '\0');
writeFlags(ss, mer.dwEventFlags, "flags", kMouseEventFlags, ' ', ' ', '\0');
writeFlags(ss, buttons, "buttons", kButtonStates, ' ', ' ', '\0');
if (wheel != 0) {
ss << " wheel=" << std::dec << wheel;
}
return ss.str();
}
void debugShowInput(bool enableMouse) {
HANDLE conin = GetStdHandle(STD_INPUT_HANDLE);
DWORD origConsoleMode = 0;
if (!GetConsoleMode(conin, &origConsoleMode)) {
fprintf(stderr, "Error: could not read console mode -- "
"is STDIN a console handle?\n");
exit(1);
}
DWORD newConsoleMode = origConsoleMode;
newConsoleMode &= ~ENABLE_PROCESSED_INPUT;
newConsoleMode &= ~ENABLE_LINE_INPUT;
newConsoleMode &= ~ENABLE_ECHO_INPUT;
if (enableMouse) {
newConsoleMode |= ENABLE_MOUSE_INPUT;
} else {
newConsoleMode &= ~ENABLE_MOUSE_INPUT;
}
if (!SetConsoleMode(conin, newConsoleMode)) {
fprintf(stderr, "Error: could not set console mode\n");
exit(1);
}
printf("\nPress any keys -- Ctrl-D exits\n\n");
INPUT_RECORD records[32];
DWORD actual = 0;
bool finished = false;
while (!finished &&
ReadConsoleInputW(conin, records, 32, &actual) && actual >= 1) {
std::stringstream ss;
for (DWORD i = 0; i < actual; ++i) {
const INPUT_RECORD &record = records[i];
if (record.EventType == KEY_EVENT) {
const KEY_EVENT_RECORD &ker = record.Event.KeyEvent;
InputMap::Key key = {
ker.wVirtualKeyCode,
ker.uChar.UnicodeChar,
static_cast<uint16_t>(ker.dwControlKeyState),
};
ss << "key: " << (ker.bKeyDown ? "dn" : "up")
<< " rpt=" << std::dec << ker.wRepeatCount
<< " scn=" << std::dec << ker.wVirtualScanCode
<< ' ' << key.toString() << '\n';
if ((ker.dwControlKeyState & LEFT_CTRL_PRESSED) &&
ker.wVirtualKeyCode == 'D') {
finished = true;
break;
}
} else if (record.EventType == MOUSE_EVENT) {
const MOUSE_EVENT_RECORD &mer = record.Event.MouseEvent;
ss << "mouse: " << mouseEventToString(mer).c_str() << '\n';
} else if (record.EventType == WINDOW_BUFFER_SIZE_EVENT) {
const WINDOW_BUFFER_SIZE_RECORD &wbsr =
record.Event.WindowBufferSizeEvent;
ss << "buffer-resized: dwSize=("
<< std::dec << wbsr.dwSize.X << ','
<< wbsr.dwSize.Y << ")\n";
} else if (record.EventType == MENU_EVENT) {
const MENU_EVENT_RECORD &mer = record.Event.MenuEvent;
ss << "menu-event: commandId=0x"
<< std::hex << mer.dwCommandId << '\n';
} else if (record.EventType == FOCUS_EVENT) {
const FOCUS_EVENT_RECORD &fer = record.Event.FocusEvent;
ss << "focus: " << (fer.bSetFocus ? "gained" : "lost") << '\n';
}
}
std::cout << ss.str();
}
SetConsoleMode(conin, origConsoleMode);
}

32
src/agent/DebugShowInput.h Executable file
View File

@ -0,0 +1,32 @@
// Copyright (c) 2015 Ryan Prichard
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
#ifndef AGENT_DEBUG_SHOW_INPUT_H
#define AGENT_DEBUG_SHOW_INPUT_H
#include <windows.h>
#include <string>
std::string controlKeyStatePrefix(DWORD controlKeyState);
std::string mouseEventToString(const MOUSE_EVENT_RECORD &mer);
void debugShowInput(bool enableMouse);
#endif // AGENT_DEBUG_SHOW_INPUT_H

View File

@ -25,6 +25,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "DebugShowInput.h"
#include "SimplePool.h" #include "SimplePool.h"
#include "../shared/DebugClient.h" #include "../shared/DebugClient.h"
#include "../shared/UnixCtrlChars.h" #include "../shared/UnixCtrlChars.h"
@ -112,15 +113,7 @@ static const char *getVirtualKeyString(int virtualKey)
std::string InputMap::Key::toString() const { std::string InputMap::Key::toString() const {
std::string ret; std::string ret;
if (keyState & CAPSLOCK_ON) { ret += "CapsLock-"; } ret += controlKeyStatePrefix(keyState);
if (keyState & ENHANCED_KEY) { ret += "Enhanced-"; }
if (keyState & LEFT_ALT_PRESSED) { ret += "LAlt-"; }
if (keyState & LEFT_CTRL_PRESSED) { ret += "LCtrl-"; }
if (keyState & NUMLOCK_ON) { ret += "NumLock-"; }
if (keyState & RIGHT_ALT_PRESSED) { ret += "RAlt-"; }
if (keyState & RIGHT_CTRL_PRESSED) { ret += "RCtrl-"; }
if (keyState & SCROLLLOCK_ON) { ret += "ScrollLock-"; }
if (keyState & SHIFT_PRESSED) { ret += "Shift-"; }
char buf[256]; char buf[256];
const char *vkString = getVirtualKeyString(virtualKey); const char *vkString = getVirtualKeyString(virtualKey);
if (vkString != NULL) { if (vkString != NULL) {

View File

@ -22,7 +22,7 @@
#include <stdlib.h> #include <stdlib.h>
#include "Agent.h" #include "Agent.h"
#include "InputMap.h" #include "DebugShowInput.h"
#include "../shared/WinptyAssert.h" #include "../shared/WinptyAssert.h"
#include "../shared/WinptyVersion.h" #include "../shared/WinptyVersion.h"
@ -36,8 +36,10 @@ const char USAGE[] =
"Usage: %s [options]\n" "Usage: %s [options]\n"
"\n" "\n"
"Options:\n" "Options:\n"
" --showkey Dump KEY_EVENT records read from the console input buffer\n" " --show-input Dump INPUT_RECORDs from the console input buffer\n"
" --version Print the winpty version\n"; " --show-input --with-mouse\n"
" Include MOUSE_INPUT_RECORDs in the dump output\n"
" --version Print the winpty version\n";
static wchar_t *heapMbsToWcs(const char *text) static wchar_t *heapMbsToWcs(const char *text)
{ {
@ -49,45 +51,6 @@ static wchar_t *heapMbsToWcs(const char *text)
return ret; return ret;
} }
static void debugShowKey()
{
HANDLE conin = GetStdHandle(STD_INPUT_HANDLE);
DWORD consoleMode = 0;
if (!GetConsoleMode(conin, &consoleMode) ||
!SetConsoleMode(conin, consoleMode &
~(ENABLE_PROCESSED_INPUT |
ENABLE_LINE_INPUT |
ENABLE_ECHO_INPUT))) {
printf("Error: could not set console mode -- "
"is STDIN a console handle?\n");
exit(1);
}
printf("\nPress any keys -- Ctrl-D exits\n\n");
INPUT_RECORD record;
DWORD actual = 0;
while (ReadConsoleInputW(conin, &record, 1, &actual) && actual == 1) {
if (record.EventType != KEY_EVENT) {
continue;
}
KEY_EVENT_RECORD &ker = record.Event.KeyEvent;
InputMap::Key key = {
ker.wVirtualKeyCode,
ker.uChar.UnicodeChar,
static_cast<uint16_t>(ker.dwControlKeyState),
};
printf("%s rpt=%d scn=%d %s\n",
ker.bKeyDown ? "dn" : "up",
ker.wRepeatCount,
ker.wVirtualScanCode,
key.toString().c_str());
if ((ker.dwControlKeyState & LEFT_CTRL_PRESSED) &&
ker.wVirtualKeyCode == 'D') {
break;
}
}
SetConsoleMode(conin, consoleMode);
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
if (argc == 2 && !strcmp(argv[1], "--version")) { if (argc == 2 && !strcmp(argv[1], "--version")) {
@ -95,8 +58,11 @@ int main(int argc, char *argv[])
return 0; return 0;
} }
if (argc == 2 && !strcmp(argv[1], "--showkey")) { if (argc == 2 && !strcmp(argv[1], "--show-input")) {
debugShowKey(); debugShowInput(false);
return 0;
} else if (argc == 3 && !strcmp(argv[1], "--show-input") && !strcmp(argv[2], "--with-mouse")) {
debugShowInput(true);
return 0; return 0;
} }

View File

@ -26,6 +26,7 @@ AGENT_OBJECTS = \
build/mingw/agent/ConsoleInput.o \ build/mingw/agent/ConsoleInput.o \
build/mingw/agent/ConsoleLine.o \ build/mingw/agent/ConsoleLine.o \
build/mingw/agent/Coord.o \ build/mingw/agent/Coord.o \
build/mingw/agent/DebugShowInput.o \
build/mingw/agent/DefaultInputMap.o \ build/mingw/agent/DefaultInputMap.o \
build/mingw/agent/EventLoop.o \ build/mingw/agent/EventLoop.o \
build/mingw/agent/InputMap.o \ build/mingw/agent/InputMap.o \

View File

@ -38,6 +38,8 @@
'agent/ConsoleLine.h', 'agent/ConsoleLine.h',
'agent/Coord.h', 'agent/Coord.h',
'agent/Coord.cc', 'agent/Coord.cc',
'agent/DebugShowInput.h',
'agent/DebugShowInput.cc',
'agent/DefaultInputMap.h', 'agent/DefaultInputMap.h',
'agent/DefaultInputMap.cc', 'agent/DefaultInputMap.cc',
'agent/DsrSender.h', 'agent/DsrSender.h',