/* * Send a mouse event from the client to the guest OS * * The QEMU mouse can be in either relative, or absolute mode. * Movement is sent separately from button state, which has to * be encoded as virtual key events. We also don't actually get * given any button up/down events, so have to track changes in * the button state. */ static void xenfb_mouse_event(void *opaque, int dx, int dy, int dz, int button_state) { struct XenInput *xenfb = opaque; DisplaySurface *surface = qemu_console_surface(xenfb->c.con); int dw = surface_width(surface); int dh = surface_height(surface); int i; trace_xenfb_mouse_event(opaque, dx, dy, dz, button_state, xenfb->abs_pointer_wanted); if (xenfb->abs_pointer_wanted) xenfb_send_position(xenfb, dx * (dw - 1) / 0x7fff, dy * (dh - 1) / 0x7fff, dz); else xenfb_send_motion(xenfb, dx, dy, dz); for (i = 0 ; i < 8 ; i++) { int lastDown = xenfb->button_state & (1 << i); int down = button_state & (1 << i); if (down == lastDown) continue; if (xenfb_send_key(xenfb, down, BTN_LEFT+i) < 0) return; } xenfb->button_state = button_state; }
/* * Send a mouse event from the client to the guest OS * * The QEMU mouse can be in either relative, or absolute mode. * Movement is sent separately from button state, which has to * be encoded as virtual key events. We also don't actually get * given any button up/down events, so have to track changes in * the button state. */ static void xenfb_mouse_event(void *opaque, int dx, int dy, int dz, int button_state) { struct XenInput *xenfb = opaque; int dw = ds_get_width(xenfb->c.ds); int dh = ds_get_height(xenfb->c.ds); int i; if (xenfb->abs_pointer_wanted) xenfb_send_position(xenfb, dx * (dw - 1) / 0x7fff, dy * (dh - 1) / 0x7fff, dz); else xenfb_send_motion(xenfb, dx, dy, dz); for (i = 0 ; i < 8 ; i++) { int lastDown = xenfb->button_state & (1 << i); int down = button_state & (1 << i); if (down == lastDown) continue; if (xenfb_send_key(xenfb, down, BTN_LEFT+i) < 0) return; } xenfb->button_state = button_state; }
/* * Send a key event from the client to the guest OS * QEMU gives us a raw scancode from an AT / PS/2 style keyboard. * We have to turn this into a Linux Input layer keycode. * * Extra complexity from the fact that with extended scancodes * (like those produced by arrow keys) this method gets called * twice, but we only want to send a single event. So we have to * track the '0xe0' scancode state & collapse the extended keys * as needed. * * Wish we could just send scancodes straight to the guest which * already has code for dealing with this... */ static void xenfb_key_event(void *opaque, int scancode) { static int extended = 0; int down = 1; if (scancode == 0xe0) { extended = 1; return; } else if (scancode & 0x80) { scancode &= 0x7f; down = 0; } if (extended) { scancode |= 0x80; extended = 0; } xenfb_send_key(opaque, down, scancode2linux[scancode]); }
/* * Send a key event from the client to the guest OS * QEMU gives us a QCode. * We have to turn this into a Linux Input layer keycode. * * Wish we could just send scancodes straight to the guest which * already has code for dealing with this... */ static void xenfb_key_event(DeviceState *dev, QemuConsole *src, InputEvent *evt) { struct XenInput *xenfb = (struct XenInput *)dev; InputKeyEvent *key = evt->u.key.data; int qcode = qemu_input_key_value_to_qcode(key->key); int lnx; if (qcode < qemu_input_map_qcode_to_linux_len) { lnx = qemu_input_map_qcode_to_linux[qcode]; if (lnx) { trace_xenfb_key_event(xenfb, lnx, key->down); xenfb_send_key(xenfb, key->down, lnx); } } }
/* * Send a key event from the client to the guest OS * QEMU gives us a raw scancode from an AT / PS/2 style keyboard. * We have to turn this into a Linux Input layer keycode. * * Extra complexity from the fact that with extended scancodes * (like those produced by arrow keys) this method gets called * twice, but we only want to send a single event. So we have to * track the '0xe0' scancode state & collapse the extended keys * as needed. * * Wish we could just send scancodes straight to the guest which * already has code for dealing with this... */ static void xenfb_key_event(void *opaque, int scancode) { struct XenInput *xenfb = opaque; int down = 1; if (scancode == 0xe0) { xenfb->extended = 1; return; } else if (scancode & 0x80) { scancode &= 0x7f; down = 0; } if (xenfb->extended) { scancode |= 0x80; xenfb->extended = 0; } xenfb_send_key(xenfb, down, scancode2linux[scancode]); }
/* * Send a mouse event from the client to the guest OS * * The QEMU mouse can be in either relative, or absolute mode. * Movement is sent separately from button state, which has to * be encoded as virtual key events. We also don't actually get * given any button up/down events, so have to track changes in * the button state. */ static void xenfb_mouse_event(void *opaque, int dx, int dy, int dz, int button_state) { int i; struct xenfb *xenfb = opaque; if (xenfb->abs_pointer_wanted) xenfb_send_position(xenfb, dx * (xenfb->ds->width - 1) / 0x7fff, dy * (xenfb->ds->height - 1) / 0x7fff, dz); else xenfb_send_motion(xenfb, dx, dy, dz); for (i = 0 ; i < 8 ; i++) { int lastDown = xenfb->button_state & (1 << i); int down = button_state & (1 << i); if (down == lastDown) continue; if (xenfb_send_key(xenfb, down, BTN_LEFT+i) < 0) return; } xenfb->button_state = button_state; }
/* * Send a mouse event from the client to the guest OS * * The QEMU mouse can be in either relative, or absolute mode. * Movement is sent separately from button state, which has to * be encoded as virtual key events. We also don't actually get * given any button up/down events, so have to track changes in * the button state. */ static void xenfb_mouse_event(DeviceState *dev, QemuConsole *src, InputEvent *evt) { struct XenInput *xenfb = (struct XenInput *)dev; InputBtnEvent *btn; InputMoveEvent *move; QemuConsole *con; DisplaySurface *surface; int scale; switch (evt->type) { case INPUT_EVENT_KIND_BTN: btn = evt->u.btn.data; switch (btn->button) { case INPUT_BUTTON_LEFT: xenfb_send_key(xenfb, btn->down, BTN_LEFT); break; case INPUT_BUTTON_RIGHT: xenfb_send_key(xenfb, btn->down, BTN_LEFT + 1); break; case INPUT_BUTTON_MIDDLE: xenfb_send_key(xenfb, btn->down, BTN_LEFT + 2); break; case INPUT_BUTTON_WHEEL_UP: if (btn->down) { xenfb->wheel--; } break; case INPUT_BUTTON_WHEEL_DOWN: if (btn->down) { xenfb->wheel++; } break; default: break; } break; case INPUT_EVENT_KIND_ABS: move = evt->u.abs.data; if (xenfb->raw_pointer_wanted) { xenfb->axis[move->axis] = move->value; } else { con = qemu_console_lookup_by_index(0); if (!con) { xen_pv_printf(&xenfb->c.xendev, 0, "No QEMU console available"); return; } surface = qemu_console_surface(con); switch (move->axis) { case INPUT_AXIS_X: scale = surface_width(surface) - 1; break; case INPUT_AXIS_Y: scale = surface_height(surface) - 1; break; default: scale = 0x8000; break; } xenfb->axis[move->axis] = move->value * scale / 0x7fff; } break; case INPUT_EVENT_KIND_REL: move = evt->u.rel.data; xenfb->axis[move->axis] += move->value; break; default: break; } }