Home | History | Annotate | Download | only in qemu
      1 /*
      2  * QEMU System Emulator
      3  *
      4  * Copyright (c) 2003-2008 Fabrice Bellard
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a copy
      7  * of this software and associated documentation files (the "Software"), to deal
      8  * in the Software without restriction, including without limitation the rights
      9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10  * copies of the Software, and to permit persons to whom the Software is
     11  * furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     22  * THE SOFTWARE.
     23  */
     24 
     25 #include "sysemu.h"
     26 #include "net.h"
     27 #include "monitor.h"
     28 #include "console.h"
     29 #include "qjson.h"
     30 
     31 #ifdef CONFIG_SKINNING
     32 QEMUPutMouseEntry *original_qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
     33                                                          void *opaque, int absolute,
     34                                                          const char *name);
     35 #undef qemu_add_mouse_event_handler
     36 #define qemu_add_mouse_event_handler original_qemu_add_mouse_event_handler
     37 #endif
     38 static QTAILQ_HEAD(, QEMUPutKBDEntry) kbd_handlers =
     39     QTAILQ_HEAD_INITIALIZER(kbd_handlers);
     40 static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers = QTAILQ_HEAD_INITIALIZER(led_handlers);
     41 static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers =
     42     QTAILQ_HEAD_INITIALIZER(mouse_handlers);
     43 static NotifierList mouse_mode_notifiers =
     44     NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers);
     45 
     46 void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
     47 {
     48     QEMUPutKBDEntry *s;
     49 
     50     if (func != NULL) {
     51         s = qemu_mallocz(sizeof(QEMUPutKBDEntry));
     52 
     53         s->put_kbd_event = func;
     54         s->opaque = opaque;
     55 
     56         QTAILQ_INSERT_TAIL(&kbd_handlers, s, next);
     57     }
     58 }
     59 
     60 void qemu_remove_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
     61 {
     62     QEMUPutKBDEntry *cursor, *cursor_next;
     63     if (func != NULL) {
     64         QTAILQ_FOREACH_SAFE(cursor, &kbd_handlers, next, cursor_next) {
     65             if (cursor->put_kbd_event == func && cursor->opaque == opaque) {
     66                 QTAILQ_REMOVE(&kbd_handlers, cursor, next);
     67             }
     68         }
     69     }
     70 }
     71 
     72 static void check_mode_change(void)
     73 {
     74     static int current_is_absolute, current_has_absolute;
     75     int is_absolute;
     76     int has_absolute;
     77 
     78     is_absolute = kbd_mouse_is_absolute();
     79     has_absolute = kbd_mouse_has_absolute();
     80 
     81     if (is_absolute != current_is_absolute ||
     82         has_absolute != current_has_absolute) {
     83         notifier_list_notify(&mouse_mode_notifiers);
     84     }
     85 
     86     current_is_absolute = is_absolute;
     87     current_has_absolute = has_absolute;
     88 }
     89 
     90 QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
     91                                                 void *opaque, int absolute,
     92                                                 const char *name)
     93 {
     94     QEMUPutMouseEntry *s;
     95     static int mouse_index = 0;
     96 
     97     s = qemu_mallocz(sizeof(QEMUPutMouseEntry));
     98 
     99     s->qemu_put_mouse_event = func;
    100     s->qemu_put_mouse_event_opaque = opaque;
    101     s->qemu_put_mouse_event_absolute = absolute;
    102     s->qemu_put_mouse_event_name = qemu_strdup(name);
    103     s->index = mouse_index++;
    104 
    105     QTAILQ_INSERT_TAIL(&mouse_handlers, s, node);
    106 
    107     check_mode_change();
    108 
    109     return s;
    110 }
    111 
    112 void qemu_activate_mouse_event_handler(QEMUPutMouseEntry *entry)
    113 {
    114     QTAILQ_REMOVE(&mouse_handlers, entry, node);
    115     QTAILQ_INSERT_HEAD(&mouse_handlers, entry, node);
    116 
    117     check_mode_change();
    118 }
    119 
    120 void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry)
    121 {
    122     QTAILQ_REMOVE(&mouse_handlers, entry, node);
    123 
    124     qemu_free(entry->qemu_put_mouse_event_name);
    125     qemu_free(entry);
    126 
    127     check_mode_change();
    128 }
    129 
    130 QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func,
    131                                             void *opaque)
    132 {
    133     QEMUPutLEDEntry *s;
    134 
    135     s = qemu_mallocz(sizeof(QEMUPutLEDEntry));
    136 
    137     s->put_led = func;
    138     s->opaque = opaque;
    139     QTAILQ_INSERT_TAIL(&led_handlers, s, next);
    140     return s;
    141 }
    142 
    143 void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
    144 {
    145     if (entry == NULL)
    146         return;
    147     QTAILQ_REMOVE(&led_handlers, entry, next);
    148     qemu_free(entry);
    149 }
    150 
    151 void kbd_put_keycode(int keycode)
    152 {
    153     QEMUPutKBDEntry *cursor;
    154     QTAILQ_FOREACH(cursor, &kbd_handlers, next) {
    155         cursor->put_kbd_event(cursor->opaque, keycode);
    156     }
    157 }
    158 
    159 void kbd_put_ledstate(int ledstate)
    160 {
    161     QEMUPutLEDEntry *cursor;
    162 
    163     QTAILQ_FOREACH(cursor, &led_handlers, next) {
    164         cursor->put_led(cursor->opaque, ledstate);
    165     }
    166 }
    167 
    168 void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
    169 {
    170     QEMUPutMouseEntry *entry;
    171     QEMUPutMouseEvent *mouse_event;
    172     void *mouse_event_opaque;
    173 #ifndef CONFIG_SKINNING
    174     int width;
    175 #endif
    176 
    177     if (QTAILQ_EMPTY(&mouse_handlers)) {
    178         return;
    179     }
    180 
    181     entry = QTAILQ_FIRST(&mouse_handlers);
    182 
    183     mouse_event = entry->qemu_put_mouse_event;
    184     mouse_event_opaque = entry->qemu_put_mouse_event_opaque;
    185 
    186     if (mouse_event) {
    187 #ifndef CONFIG_SKINNING
    188         if (graphic_rotate) {
    189             if (entry->qemu_put_mouse_event_absolute) {
    190                 width = 0x7fff;
    191             } else {
    192                 width = graphic_width - 1;
    193             }
    194             mouse_event(mouse_event_opaque, width - dy, dx, dz, buttons_state);
    195         } else {
    196             mouse_event(mouse_event_opaque, dx, dy, dz, buttons_state);
    197         }
    198 #else
    199         mouse_event(mouse_event_opaque, dx, dy, dz, buttons_state);
    200 #endif
    201     }
    202 }
    203 
    204 int kbd_mouse_is_absolute(void)
    205 {
    206     if (QTAILQ_EMPTY(&mouse_handlers)) {
    207         return 0;
    208     }
    209 
    210     return QTAILQ_FIRST(&mouse_handlers)->qemu_put_mouse_event_absolute;
    211 }
    212 
    213 int kbd_mouse_has_absolute(void)
    214 {
    215     QEMUPutMouseEntry *entry;
    216 
    217     QTAILQ_FOREACH(entry, &mouse_handlers, node) {
    218         if (entry->qemu_put_mouse_event_absolute) {
    219             return 1;
    220         }
    221     }
    222 
    223     return 0;
    224 }
    225 
    226 static void info_mice_iter(QObject *data, void *opaque)
    227 {
    228     QDict *mouse;
    229     Monitor *mon = opaque;
    230 
    231     mouse = qobject_to_qdict(data);
    232     monitor_printf(mon, "%c Mouse #%" PRId64 ": %s%s\n",
    233                   (qdict_get_bool(mouse, "current") ? '*' : ' '),
    234                    qdict_get_int(mouse, "index"), qdict_get_str(mouse, "name"),
    235                    qdict_get_bool(mouse, "absolute") ? " (absolute)" : "");
    236 }
    237 
    238 void do_info_mice_print(Monitor *mon, const QObject *data)
    239 {
    240     QList *mice_list;
    241 
    242     mice_list = qobject_to_qlist(data);
    243     if (qlist_empty(mice_list)) {
    244         monitor_printf(mon, "No mouse devices connected\n");
    245         return;
    246     }
    247 
    248     qlist_iter(mice_list, info_mice_iter, mon);
    249 }
    250 
    251 void do_info_mice(Monitor *mon, QObject **ret_data)
    252 {
    253     QEMUPutMouseEntry *cursor;
    254     QList *mice_list;
    255     int current;
    256 
    257     mice_list = qlist_new();
    258 
    259     if (QTAILQ_EMPTY(&mouse_handlers)) {
    260         goto out;
    261     }
    262 
    263     current = QTAILQ_FIRST(&mouse_handlers)->index;
    264 
    265     QTAILQ_FOREACH(cursor, &mouse_handlers, node) {
    266         QObject *obj;
    267         obj = qobject_from_jsonf("{ 'name': %s,"
    268                                  "  'index': %d,"
    269                                  "  'current': %i,"
    270                                  "  'absolute': %i }",
    271                                  cursor->qemu_put_mouse_event_name,
    272                                  cursor->index,
    273                                  cursor->index == current,
    274                                  !!cursor->qemu_put_mouse_event_absolute);
    275         qlist_append_obj(mice_list, obj);
    276     }
    277 
    278 out:
    279     *ret_data = QOBJECT(mice_list);
    280 }
    281 
    282 void do_mouse_set(Monitor *mon, const QDict *qdict)
    283 {
    284     QEMUPutMouseEntry *cursor;
    285     int index = qdict_get_int(qdict, "index");
    286     int found = 0;
    287 
    288     if (QTAILQ_EMPTY(&mouse_handlers)) {
    289         monitor_printf(mon, "No mouse devices connected\n");
    290         return;
    291     }
    292 
    293     QTAILQ_FOREACH(cursor, &mouse_handlers, node) {
    294         if (cursor->index == index) {
    295             found = 1;
    296             qemu_activate_mouse_event_handler(cursor);
    297             break;
    298         }
    299     }
    300 
    301     if (!found) {
    302         monitor_printf(mon, "Mouse at given index not found\n");
    303     }
    304 
    305     check_mode_change();
    306 }
    307 
    308 void qemu_add_mouse_mode_change_notifier(Notifier *notify)
    309 {
    310     notifier_list_add(&mouse_mode_notifiers, notify);
    311 }
    312 
    313 void qemu_remove_mouse_mode_change_notifier(Notifier *notify)
    314 {
    315     notifier_list_remove(&mouse_mode_notifiers, notify);
    316 }
    317