int ConsoleInput::scanMouseInput()

in src/agent/ConsoleInput.cc [488:599]


int ConsoleInput::scanMouseInput(std::vector<INPUT_RECORD> &records,
                                 const char *input,
                                 int inputSize)
{
    MouseRecord record;
    const int len = matchMouseRecord(input, inputSize, record);
    if (len <= 0) {
        return len;
    }

    if (isTracingEnabled()) {
        static bool debugInput = hasDebugFlag("input");
        if (debugInput) {
            trace("mouse input: %s", record.toString().c_str());
        }
    }

    const int button = record.flags & 0x03;
    INPUT_RECORD newRecord = {0};
    newRecord.EventType = MOUSE_EVENT;
    MOUSE_EVENT_RECORD &mer = newRecord.Event.MouseEvent;

    mer.dwMousePosition.X =
        m_mouseWindowRect.Left +
            std::max(0, std::min<int>(record.coord.X,
                                      m_mouseWindowRect.width() - 1));

    mer.dwMousePosition.Y =
        m_mouseWindowRect.Top +
            std::max(0, std::min<int>(record.coord.Y,
                                      m_mouseWindowRect.height() - 1));

    // The modifier state is neatly independent of everything else.
    if (record.flags & 0x04) { mer.dwControlKeyState |= SHIFT_PRESSED;     }
    if (record.flags & 0x08) { mer.dwControlKeyState |= LEFT_ALT_PRESSED;  }
    if (record.flags & 0x10) { mer.dwControlKeyState |= LEFT_CTRL_PRESSED; }

    if (record.flags & 0x40) {
        // Mouse wheel
        mer.dwEventFlags |= MOUSE_WHEELED;
        if (button == 0) {
            // up
            mer.dwButtonState |= 0x00780000;
        } else if (button == 1) {
            // down
            mer.dwButtonState |= 0xff880000;
        } else {
            // Invalid -- do nothing
            return len;
        }
    } else {
        // Ordinary mouse event
        if (record.flags & 0x20) { mer.dwEventFlags |= MOUSE_MOVED; }
        if (button == 3) {
            m_mouseButtonState = 0;
            // Potentially advance double-click detection.
            m_doubleClick.released = true;
        } else {
            const DWORD relevantFlag =
                (button == 0) ? FROM_LEFT_1ST_BUTTON_PRESSED :
                (button == 1) ? FROM_LEFT_2ND_BUTTON_PRESSED :
                (button == 2) ? RIGHTMOST_BUTTON_PRESSED :
                0;
            ASSERT(relevantFlag != 0);
            if (record.release) {
                m_mouseButtonState &= ~relevantFlag;
                if (relevantFlag == m_doubleClick.button) {
                    // Potentially advance double-click detection.
                    m_doubleClick.released = true;
                } else {
                    // End double-click detection.
                    m_doubleClick = DoubleClickDetection();
                }
            } else if ((m_mouseButtonState & relevantFlag) == 0) {
                // The button has been newly pressed.
                m_mouseButtonState |= relevantFlag;
                // Detect a double-click.  This code looks for an exact
                // coordinate match, which is stricter than what Windows does,
                // but Windows has pixel coordinates, and we only have terminal
                // coordinates.
                if (m_doubleClick.button == relevantFlag &&
                        m_doubleClick.pos == record.coord &&
                        (GetTickCount() - m_doubleClick.tick <
                            GetDoubleClickTime())) {
                    // Record a double-click and end double-click detection.
                    mer.dwEventFlags |= DOUBLE_CLICK;
                    m_doubleClick = DoubleClickDetection();
                } else {
                    // Begin double-click detection.
                    m_doubleClick.button = relevantFlag;
                    m_doubleClick.pos = record.coord;
                    m_doubleClick.tick = GetTickCount();
                }
            }
        }
    }

    mer.dwButtonState |= m_mouseButtonState;

    if (m_mouseInputEnabled && !m_quickEditEnabled) {
        if (isTracingEnabled()) {
            static bool debugInput = hasDebugFlag("input");
            if (debugInput) {
                trace("mouse event: %s", mouseEventToString(mer).c_str());
            }
        }

        records.push_back(newRecord);
    }

    return len;
}