Examples of keyboard and mouse input handlers

For your convenience, below are excerpts from our sample applications that illustrate how postMouseEvent and postKeyEvent have been implemented.

These examples provide you with a base code that you can use to implement input event handlers in your own applications.

Mouse events

C++ on Linux Qt

void ScribbleArea::PostMouseEvent(const CSI::PureWeb::Ui::PureWebMouseEventArgs& mouseEvent)
{
    QEvent::Type action = QEvent::None;
    Qt::MouseButton button;
    Qt::MouseButtons buttons;
    Qt::KeyboardModifiers keys = 0;
						
    switch(mouseEvent.EventType)
    {
        case CSI::PureWeb::Ui::MouseEventType::MouseDown:
            action = QEvent::MouseButtonPress;
            break;
        case CSI::PureWeb::Ui::MouseEventType::MouseUp:
            action = QEvent::MouseButtonRelease;
            break;
        case CSI::PureWeb::Ui::MouseEventType::MouseMove:
            action = QEvent::MouseMove;
            break;
        default:
            return;
            break;
    }
						
    switch (mouseEvent.ChangedButton)
    {
        case CSI::PureWeb::Ui::MouseButtons::Left:
            button = Qt::LeftButton;
            break;
        case CSI::PureWeb::Ui::MouseButtons::Right:
            button = Qt::RightButton;
            break;
        default:
            button = Qt::NoButton;
            break;
    }
						
    if (0 != (mouseEvent.Buttons & Ui::MouseButtons::Left))     buttons |= Qt::LeftButton;
    if (0 != (mouseEvent.Buttons & Ui::MouseButtons::Right))    buttons |= Qt::RightButton;
    if (0 != (mouseEvent.Buttons & Ui::MouseButtons::Middle))   buttons |= Qt::MidButton;
    if (0 != (mouseEvent.Buttons & Ui::MouseButtons::XButton1)) buttons |= Qt::XButton1;
    if (0 != (mouseEvent.Buttons & Ui::MouseButtons::XButton2)) buttons |= Qt::XButton2;
    if (0 != (mouseEvent.Modifiers & Ui::Modifiers::Shift))     keys |= Qt::ShiftModifier;
    if (0 != (mouseEvent.Modifiers & Ui::Modifiers::Control))   keys |= Qt::ControlModifier;
						
    QMouseEvent * m = new QMouseEvent(action, QPoint(mouseEvent.X,mouseEvent.Y), button, buttons, keys);
    QCoreApplication::postEvent(this, m);
}

C++ on Windows

void CScribbleView::PostMouseEvent(const Ui::PureWebMouseEventArgs& mouseEvent)
{
    Ui::MouseEventType::Enum mouseEventType = mouseEvent.EventType;

    WPARAM wParam = 0;
    LPARAM lParam = 0;
    UINT message = 0;

    // wParam
    if (0 != (mouseEvent.Modifiers & Ui::Modifiers::Shift))     wParam |= MK_SHIFT;
    if (0 != (mouseEvent.Modifiers & Ui::Modifiers::Control))   wParam |= MK_CONTROL;
    if (0 != (mouseEvent.Buttons & Ui::MouseButtons::Left))     wParam |= MK_LBUTTON;
    if (0 != (mouseEvent.Buttons & Ui::MouseButtons::Right))    wParam |= MK_RBUTTON;
    if (0 != (mouseEvent.Buttons & Ui::MouseButtons::Middle))   wParam |= MK_MBUTTON;
    if (0 != (mouseEvent.Buttons & Ui::MouseButtons::XButton1)) wParam |= MK_XBUTTON1;
    if (0 != (mouseEvent.Buttons & Ui::MouseButtons::XButton2)) wParam |= MK_XBUTTON2;

    // for negative X coordinates we need to mask the first 16 bits otherwise the
    // following "OR" bitwise operation will not be correct
    lParam = (int) mouseEvent.X & 0x0000ffff;  
    lParam |= ((int)mouseEvent.Y) << 16;

    switch (mouseEventType)
    {
    case Ui::MouseEventType::MouseEnter:
        //OnMouseEnter(EventArgs.Empty);
        return;

    case Ui::MouseEventType::MouseLeave:
        //OnMouseLeave(EventArgs.Empty);
        return;

    case Ui::MouseEventType::MouseMove:
        message = WM_MOUSEMOVE;
        break;

    case Ui::MouseEventType::MouseDown:
        if (0 != (mouseEvent.ChangedButton & Ui::MouseButtons::Left))
        {
             message = WM_LBUTTONDOWN;
        }
        else if (0 != (mouseEvent.ChangedButton & Ui::MouseButtons::Right))
        {
             message = WM_RBUTTONDOWN;
        }
        else if (0 != (mouseEvent.ChangedButton & Ui::MouseButtons::Middle))
        {
            message = WM_MBUTTONDOWN;
        }
        else if (0 != (mouseEvent.ChangedButton & Ui::MouseButtons::XButton1))
        {
            message = WM_XBUTTONDOWN;
            wParam |= XBUTTON1 << 16; 
        }
        else if (0 != (mouseEvent.ChangedButton & Ui::MouseButtons::XButton2))
        {
            message = WM_XBUTTONDOWN;
            wParam |= XBUTTON2 << 16;
        }
        break;

    case Ui::MouseEventType::MouseUp:
        if (0 != (mouseEvent.ChangedButton & Ui::MouseButtons::Left))
        {
            message = WM_LBUTTONUP;
        }
        else if (0 != (mouseEvent.ChangedButton & Ui::MouseButtons::Right))
        {
            message = WM_RBUTTONUP;
        }
        else if (0 != (mouseEvent.ChangedButton & Ui::MouseButtons::Middle))
        {
            message = WM_MBUTTONUP;
        }
        else if (0 != (mouseEvent.ChangedButton & Ui::MouseButtons::XButton1))
        {
            message = WM_XBUTTONUP;
            wParam |= XBUTTON1 << 16;
        }
        else if (0 != (mouseEvent.ChangedButton & Ui::MouseButtons::XButton2))
        {
            message = WM_XBUTTONUP;
            wParam |= XBUTTON2 << 16;
        }
        break;

    case Ui::MouseEventType::MouseDoubleClick:
        if (0 != (mouseEvent.ChangedButton & Ui::MouseButtons::Left))
        {
            message = WM_LBUTTONDBLCLK;
        }
        else if (0 != (mouseEvent.ChangedButton & Ui::MouseButtons::Right))
        {
            message = WM_RBUTTONDBLCLK;
        }
        else if (0 != (mouseEvent.ChangedButton & Ui::MouseButtons::Middle))
        {
            message = WM_MBUTTONDBLCLK;
        }
        else if (0 != (mouseEvent.ChangedButton & Ui::MouseButtons::XButton1))
        {
            message = WM_XBUTTONDBLCLK;
            wParam |= XBUTTON1 << 16;
        }
        else if (0 != (mouseEvent.ChangedButton & Ui::MouseButtons::XButton2))
        {
            message = WM_XBUTTONDBLCLK;
            wParam |= XBUTTON2 << 16;
        }
        break;

    case Ui::MouseEventType::MouseWheel:
        message = WM_MOUSEWHEEL;
        wParam |= ((int)mouseEvent.Delta) << 16;
        break;

    default:
        return;
    }

    if (message != 0)
    {
        ::PostMessage(m_hWnd,message, wParam, lParam);
    }
}

.Net

public void PostMouseEvent(PureWebMouseEventArgs mouseEvent)
{
    System.Windows.Forms.MouseButtons buttons = System.Windows.Forms.MouseButtons.None;
    if (0 != (mouseEvent.Buttons & PureWeb.Ui.MouseButtons.Left)) buttons |= System.Windows.Forms.MouseButtons.Left;
    if (0 != (mouseEvent.Buttons & PureWeb.Ui.MouseButtons.Right)) buttons |= System.Windows.Forms.MouseButtons.Right;
    if (0 != (mouseEvent.Buttons & PureWeb.Ui.MouseButtons.Middle)) buttons |= System.Windows.Forms.MouseButtons.Middle;
    if (0 != (mouseEvent.Buttons & PureWeb.Ui.MouseButtons.XButton1)) buttons |= System.Windows.Forms.MouseButtons.XButton1;
    if (0 != (mouseEvent.Buttons & PureWeb.Ui.MouseButtons.XButton2)) buttons |= System.Windows.Forms.MouseButtons.XButton2;

switch (mouseEvent.EventType){
    case MouseEventType.MouseEnter:
        OnMouseEnter(EventArgs.Empty);
        break;
    case MouseEventType.MouseLeave:
        OnMouseLeave(EventArgs.Empty);
        break;
    case MouseEventType.MouseMove:
        OnMouseMove(new MouseEventArgs(buttons, 0, (int)mouseEvent.X, (int)mouseEvent.Y, (int)mouseEvent.Delta));
        break;
    case MouseEventType.MouseDown:
        OnMouseDown(new MouseEventArgs(buttons, 0, (int)mouseEvent.X, (int)mouseEvent.Y, (int)mouseEvent.Delta));
        break;
    default:
        return;
    }
}		

Java

public void postMouseEvent(PureWebMouseEventArgs mouseEvent)
{
    // must be on UI thread
    UiDispatcherUtil.verifyAccess();

    // translate to AWT mouse event and dispatch
    MouseEvent awtMouseEvent = getAWTMouseEvent(mouseEvent);

    if (awtMouseEvent == null)
        return;

    dispatchEvent(awtMouseEvent);

    // if the event was a mouse button release without a drag event intervening between
    // the mouse button down event, then dispatch a mouse clicked event with a click
    // count of 1

    if (awtMouseEvent.getID() == MouseEvent.MOUSE_RELEASED)
    {
        if (!isDragging)
            dispatchEvent(new MouseEvent(this,
                                        MouseEvent.MOUSE_CLICKED,
                                        awtMouseEvent.getWhen(),
                                        awtMouseEvent.getModifiers(),
                                        awtMouseEvent.getX(),
                                        awtMouseEvent.getY(),
                                        1,
                                        false,
                                        awtMouseEvent.getButton()));
        isDragging = false;
    }
}

private MouseEvent getAWTMouseEvent(PureWebMouseEventArgs mouseEvent)
{
    int modifiers = getModifiers(mouseEvent.getModifiers());

    EnumSet<MouseButtons> buttons = mouseEvent.getButtons();

    if (buttons.contains(MouseButtons.Left))
        modifiers |= InputEvent.BUTTON1_DOWN_MASK;

    if (buttons.contains(MouseButtons.Middle))
        modifiers |= InputEvent.BUTTON2_DOWN_MASK;

    if (buttons.contains(MouseButtons.Right))
        modifiers |= InputEvent.BUTTON3_DOWN_MASK;

    int id = 0;
    int clickCount = 1;
    MouseEventType eventType = mouseEvent.getEventType();

    if (eventType == MouseEventType.MouseEnter)
        id = MouseEvent.MOUSE_ENTERED;
    else if (eventType == MouseEventType.MouseLeave)
        id = MouseEvent.MOUSE_EXITED;
    else if (eventType == MouseEventType.MouseMove)
    {
        if (buttons.contains(MouseButtons.None))
        {
            id = MouseEvent.MOUSE_MOVED;
        }
        else
        {
            id = MouseEvent.MOUSE_DRAGGED;
            isDragging = true;
        }
    }
    else if (eventType == MouseEventType.MouseDown)
    {
        id = MouseEvent.MOUSE_PRESSED;
        isDragging = false;
    }
    else if (eventType == MouseEventType.MouseUp)
        id = MouseEvent.MOUSE_RELEASED;
    else if (eventType == MouseEventType.MouseDoubleClick)
    {
        id = MouseEvent.MOUSE_CLICKED;
        clickCount = 2;
    }
    else if (eventType == MouseEventType.MouseWheel)
        id = MouseEvent.MOUSE_WHEEL;
    else
    {
        log.warn("Received unknown mouse event type {}.", eventType);
        return null;
    }

    long when = System.currentTimeMillis();
    int x = (int)mouseEvent.getX();
    int y = (int)mouseEvent.getY();

    if (eventType != MouseEventType.MouseWheel)
    {
        MouseButtons changed = mouseEvent.getChangedButton();

        int awtButton;

        if (changed == MouseButtons.Left)
            awtButton = MouseEvent.BUTTON1;
        else if (changed == MouseButtons.Middle)
            awtButton = MouseEvent.BUTTON2;
        else if (changed == MouseButtons.Right)
            awtButton = MouseEvent.BUTTON3;
        else
            awtButton = MouseEvent.NOBUTTON;

            return new MouseEvent(this, id, when, modifiers, x, y, clickCount, false, awtButton);
    }

    return new MouseWheelEvent(this, id, when, modifiers, x, y, clickCount, false,
        MouseWheelEvent.WHEEL_UNIT_SCROLL, 1, (int)-mouseEvent.getDelta());
}

private int getModifiers(Set<Modifiers> eventModifiers)
{
    int modifiers = 0;

    if (eventModifiers.contains(Modifiers.Shift))
        modifiers |= InputEvent.SHIFT_DOWN_MASK;

    if (eventModifiers.contains(Modifiers.Control))
        modifiers |= InputEvent.CTRL_DOWN_MASK;

    if (eventModifiers.contains(Modifiers.Alternate))
        modifiers |= InputEvent.ALT_DOWN_MASK;

    return modifiers;
}

Keyboard events

C++

// Views in the Scribble sample application in C++ do no support keyboard events.

.Net

// Preliminary global declarations
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
const int WM_SYSKEYDOWN = 0x104;
const int WM_SYSKEYUP = 0x105;
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
            
(...)
			
public void postKeyEvent(PureWebKeyboardEventArgs keyEvent){
    bool isAltDown = 0 != (keyEvent.Modifiers & Modifiers.Alternate);
    int wParam = (int)keyEvent.KeyCode;
    int lParam = isAltDown ? (1 << 29) : 0; // "context code";
    int message;
            
    if (isAltDown || keyEvent.KeyCode == KeyCode.F10){
        message = keyEvent.EventType == KeyboardEventType.KeyDown ? WM_SYSKEYDOWN : WM_SYSKEYUP;
    }else{
        message = keyEvent.EventType == KeyboardEventType.KeyDown ? WM_KEYDOWN : WM_KEYUP;
    }
    PostMessage(this.Handle, (UInt32)message, new IntPtr(wParam), new IntPtr(lParam));
}   

Java

public void postKeyEvent(PureWebKeyboardEventArgs keyEvent)
{
    // must be on UI thread
    UiDispatcherUtil.verifyAccess();

    // translate to AWT key event and dispatch
    int id = keyEvent.getEventType() == KeyboardEventType.KeyDown ? KeyEvent.KEY_PRESSED : KeyEvent.KEY_RELEASED;
    long when = System.currentTimeMillis();
    int modifiers = getModifiers(keyEvent.getModifiers());
    char keyChar = (char)keyEvent.getCharacterCode();
    int keyCode = keyEvent.getKeyCode().getVirtualKeyCode();

    dispatchEvent(new KeyEvent(this, id, when, modifiers, keyCode, keyChar));
}