|
|
1.1 ! root 1: /* ! 2: * Copyright (C) 2010 Red Hat, Inc. ! 3: * ! 4: * This program is free software; you can redistribute it and/or ! 5: * modify it under the terms of the GNU General Public License as ! 6: * published by the Free Software Foundation; either version 2 or ! 7: * (at your option) version 3 of the License. ! 8: * ! 9: * This program is distributed in the hope that it will be useful, ! 10: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 12: * GNU General Public License for more details. ! 13: * ! 14: * You should have received a copy of the GNU General Public License ! 15: * along with this program; if not, see <http://www.gnu.org/licenses/>. ! 16: */ ! 17: ! 18: #include <stdlib.h> ! 19: #include <stdio.h> ! 20: #include <stdbool.h> ! 21: #include <string.h> ! 22: ! 23: #include <spice.h> ! 24: #include <spice/enums.h> ! 25: ! 26: #include "qemu-common.h" ! 27: #include "qemu-spice.h" ! 28: #include "console.h" ! 29: ! 30: /* keyboard bits */ ! 31: ! 32: typedef struct QemuSpiceKbd { ! 33: SpiceKbdInstance sin; ! 34: int ledstate; ! 35: } QemuSpiceKbd; ! 36: ! 37: static void kbd_push_key(SpiceKbdInstance *sin, uint8_t frag); ! 38: static uint8_t kbd_get_leds(SpiceKbdInstance *sin); ! 39: static void kbd_leds(void *opaque, int l); ! 40: ! 41: static const SpiceKbdInterface kbd_interface = { ! 42: .base.type = SPICE_INTERFACE_KEYBOARD, ! 43: .base.description = "qemu keyboard", ! 44: .base.major_version = SPICE_INTERFACE_KEYBOARD_MAJOR, ! 45: .base.minor_version = SPICE_INTERFACE_KEYBOARD_MINOR, ! 46: .push_scan_freg = kbd_push_key, ! 47: .get_leds = kbd_get_leds, ! 48: }; ! 49: ! 50: static void kbd_push_key(SpiceKbdInstance *sin, uint8_t frag) ! 51: { ! 52: kbd_put_keycode(frag); ! 53: } ! 54: ! 55: static uint8_t kbd_get_leds(SpiceKbdInstance *sin) ! 56: { ! 57: QemuSpiceKbd *kbd = container_of(sin, QemuSpiceKbd, sin); ! 58: return kbd->ledstate; ! 59: } ! 60: ! 61: static void kbd_leds(void *opaque, int ledstate) ! 62: { ! 63: QemuSpiceKbd *kbd = opaque; ! 64: ! 65: kbd->ledstate = 0; ! 66: if (ledstate & QEMU_SCROLL_LOCK_LED) { ! 67: kbd->ledstate |= SPICE_KEYBOARD_MODIFIER_FLAGS_SCROLL_LOCK; ! 68: } ! 69: if (ledstate & QEMU_NUM_LOCK_LED) { ! 70: kbd->ledstate |= SPICE_KEYBOARD_MODIFIER_FLAGS_NUM_LOCK; ! 71: } ! 72: if (ledstate & QEMU_CAPS_LOCK_LED) { ! 73: kbd->ledstate |= SPICE_KEYBOARD_MODIFIER_FLAGS_CAPS_LOCK; ! 74: } ! 75: spice_server_kbd_leds(&kbd->sin, ledstate); ! 76: } ! 77: ! 78: /* mouse bits */ ! 79: ! 80: typedef struct QemuSpicePointer { ! 81: SpiceMouseInstance mouse; ! 82: SpiceTabletInstance tablet; ! 83: int width, height, x, y; ! 84: Notifier mouse_mode; ! 85: bool absolute; ! 86: } QemuSpicePointer; ! 87: ! 88: static int map_buttons(int spice_buttons) ! 89: { ! 90: int qemu_buttons = 0; ! 91: ! 92: /* ! 93: * Note: SPICE_MOUSE_BUTTON_* specifies the wire protocol but this ! 94: * isn't what we get passed in via interface callbacks for the ! 95: * middle and right button ... ! 96: */ ! 97: if (spice_buttons & SPICE_MOUSE_BUTTON_MASK_LEFT) { ! 98: qemu_buttons |= MOUSE_EVENT_LBUTTON; ! 99: } ! 100: if (spice_buttons & 0x04 /* SPICE_MOUSE_BUTTON_MASK_MIDDLE */) { ! 101: qemu_buttons |= MOUSE_EVENT_MBUTTON; ! 102: } ! 103: if (spice_buttons & 0x02 /* SPICE_MOUSE_BUTTON_MASK_RIGHT */) { ! 104: qemu_buttons |= MOUSE_EVENT_RBUTTON; ! 105: } ! 106: return qemu_buttons; ! 107: } ! 108: ! 109: static void mouse_motion(SpiceMouseInstance *sin, int dx, int dy, int dz, ! 110: uint32_t buttons_state) ! 111: { ! 112: kbd_mouse_event(dx, dy, dz, map_buttons(buttons_state)); ! 113: } ! 114: ! 115: static void mouse_buttons(SpiceMouseInstance *sin, uint32_t buttons_state) ! 116: { ! 117: kbd_mouse_event(0, 0, 0, map_buttons(buttons_state)); ! 118: } ! 119: ! 120: static const SpiceMouseInterface mouse_interface = { ! 121: .base.type = SPICE_INTERFACE_MOUSE, ! 122: .base.description = "mouse", ! 123: .base.major_version = SPICE_INTERFACE_MOUSE_MAJOR, ! 124: .base.minor_version = SPICE_INTERFACE_MOUSE_MINOR, ! 125: .motion = mouse_motion, ! 126: .buttons = mouse_buttons, ! 127: }; ! 128: ! 129: static void tablet_set_logical_size(SpiceTabletInstance* sin, int width, int height) ! 130: { ! 131: QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet); ! 132: ! 133: if (height < 16) { ! 134: height = 16; ! 135: } ! 136: if (width < 16) { ! 137: width = 16; ! 138: } ! 139: pointer->width = width; ! 140: pointer->height = height; ! 141: } ! 142: ! 143: static void tablet_position(SpiceTabletInstance* sin, int x, int y, ! 144: uint32_t buttons_state) ! 145: { ! 146: QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet); ! 147: ! 148: pointer->x = x * 0x7FFF / (pointer->width - 1); ! 149: pointer->y = y * 0x7FFF / (pointer->height - 1); ! 150: kbd_mouse_event(pointer->x, pointer->y, 0, map_buttons(buttons_state)); ! 151: } ! 152: ! 153: ! 154: static void tablet_wheel(SpiceTabletInstance* sin, int wheel, ! 155: uint32_t buttons_state) ! 156: { ! 157: QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet); ! 158: ! 159: kbd_mouse_event(pointer->x, pointer->y, wheel, map_buttons(buttons_state)); ! 160: } ! 161: ! 162: static void tablet_buttons(SpiceTabletInstance *sin, ! 163: uint32_t buttons_state) ! 164: { ! 165: QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet); ! 166: ! 167: kbd_mouse_event(pointer->x, pointer->y, 0, map_buttons(buttons_state)); ! 168: } ! 169: ! 170: static const SpiceTabletInterface tablet_interface = { ! 171: .base.type = SPICE_INTERFACE_TABLET, ! 172: .base.description = "tablet", ! 173: .base.major_version = SPICE_INTERFACE_TABLET_MAJOR, ! 174: .base.minor_version = SPICE_INTERFACE_TABLET_MINOR, ! 175: .set_logical_size = tablet_set_logical_size, ! 176: .position = tablet_position, ! 177: .wheel = tablet_wheel, ! 178: .buttons = tablet_buttons, ! 179: }; ! 180: ! 181: static void mouse_mode_notifier(Notifier *notifier) ! 182: { ! 183: QemuSpicePointer *pointer = container_of(notifier, QemuSpicePointer, mouse_mode); ! 184: bool is_absolute = kbd_mouse_is_absolute(); ! 185: ! 186: if (pointer->absolute == is_absolute) { ! 187: return; ! 188: } ! 189: ! 190: if (is_absolute) { ! 191: qemu_spice_add_interface(&pointer->tablet.base); ! 192: } else { ! 193: spice_server_remove_interface(&pointer->tablet.base); ! 194: } ! 195: pointer->absolute = is_absolute; ! 196: } ! 197: ! 198: void qemu_spice_input_init(void) ! 199: { ! 200: QemuSpiceKbd *kbd; ! 201: QemuSpicePointer *pointer; ! 202: ! 203: kbd = qemu_mallocz(sizeof(*kbd)); ! 204: kbd->sin.base.sif = &kbd_interface.base; ! 205: qemu_spice_add_interface(&kbd->sin.base); ! 206: qemu_add_led_event_handler(kbd_leds, kbd); ! 207: ! 208: pointer = qemu_mallocz(sizeof(*pointer)); ! 209: pointer->mouse.base.sif = &mouse_interface.base; ! 210: pointer->tablet.base.sif = &tablet_interface.base; ! 211: qemu_spice_add_interface(&pointer->mouse.base); ! 212: ! 213: pointer->absolute = false; ! 214: pointer->mouse_mode.notify = mouse_mode_notifier; ! 215: qemu_add_mouse_mode_change_notifier(&pointer->mouse_mode); ! 216: mouse_mode_notifier(&pointer->mouse_mode); ! 217: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.