Statistics
| Branch: | Revision:

root / input.c @ 48ff7a62

History | View | Annotate | Download (8.1 kB)

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
static QEMUPutKBDEvent *qemu_put_kbd_event;
32
static void *qemu_put_kbd_event_opaque;
33
static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers = QTAILQ_HEAD_INITIALIZER(led_handlers);
34
static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers =
35
    QTAILQ_HEAD_INITIALIZER(mouse_handlers);
36
static NotifierList mouse_mode_notifiers = 
37
    NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers);
38

    
39
void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
40
{
41
    qemu_put_kbd_event_opaque = opaque;
42
    qemu_put_kbd_event = func;
43
}
44

    
45
void qemu_remove_kbd_event_handler(void)
46
{
47
    qemu_put_kbd_event_opaque = NULL;
48
    qemu_put_kbd_event = NULL;
49
}
50

    
51
static void check_mode_change(void)
52
{
53
    static int current_is_absolute, current_has_absolute;
54
    int is_absolute;
55
    int has_absolute;
56

    
57
    is_absolute = kbd_mouse_is_absolute();
58
    has_absolute = kbd_mouse_has_absolute();
59

    
60
    if (is_absolute != current_is_absolute ||
61
        has_absolute != current_has_absolute) {
62
        notifier_list_notify(&mouse_mode_notifiers);
63
    }
64

    
65
    current_is_absolute = is_absolute;
66
    current_has_absolute = has_absolute;
67
}
68

    
69
QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
70
                                                void *opaque, int absolute,
71
                                                const char *name)
72
{
73
    QEMUPutMouseEntry *s;
74
    static int mouse_index = 0;
75

    
76
    s = qemu_mallocz(sizeof(QEMUPutMouseEntry));
77

    
78
    s->qemu_put_mouse_event = func;
79
    s->qemu_put_mouse_event_opaque = opaque;
80
    s->qemu_put_mouse_event_absolute = absolute;
81
    s->qemu_put_mouse_event_name = qemu_strdup(name);
82
    s->index = mouse_index++;
83

    
84
    QTAILQ_INSERT_TAIL(&mouse_handlers, s, node);
85

    
86
    check_mode_change();
87

    
88
    return s;
89
}
90

    
91
void qemu_activate_mouse_event_handler(QEMUPutMouseEntry *entry)
92
{
93
    QTAILQ_REMOVE(&mouse_handlers, entry, node);
94
    QTAILQ_INSERT_HEAD(&mouse_handlers, entry, node);
95

    
96
    check_mode_change();
97
}
98

    
99
void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry)
100
{
101
    QTAILQ_REMOVE(&mouse_handlers, entry, node);
102

    
103
    qemu_free(entry->qemu_put_mouse_event_name);
104
    qemu_free(entry);
105

    
106
    check_mode_change();
107
}
108

    
109
QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func,
110
                                            void *opaque)
111
{
112
    QEMUPutLEDEntry *s;
113

    
114
    s = qemu_mallocz(sizeof(QEMUPutLEDEntry));
115

    
116
    s->put_led = func;
117
    s->opaque = opaque;
118
    QTAILQ_INSERT_TAIL(&led_handlers, s, next);
119
    return s;
120
}
121

    
122
void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
123
{
124
    if (entry == NULL)
125
        return;
126
    QTAILQ_REMOVE(&led_handlers, entry, next);
127
    qemu_free(entry);
128
}
129

    
130
void kbd_put_keycode(int keycode)
131
{
132
    if (qemu_put_kbd_event) {
133
        qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode);
134
    }
135
}
136

    
137
void kbd_put_ledstate(int ledstate)
138
{
139
    QEMUPutLEDEntry *cursor;
140

    
141
    QTAILQ_FOREACH(cursor, &led_handlers, next) {
142
        cursor->put_led(cursor->opaque, ledstate);
143
    }
144
}
145

    
146
void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
147
{
148
    QEMUPutMouseEntry *entry;
149
    QEMUPutMouseEvent *mouse_event;
150
    void *mouse_event_opaque;
151
    int width, height;
152

    
153
    if (QTAILQ_EMPTY(&mouse_handlers)) {
154
        return;
155
    }
156

    
157
    entry = QTAILQ_FIRST(&mouse_handlers);
158

    
159
    mouse_event = entry->qemu_put_mouse_event;
160
    mouse_event_opaque = entry->qemu_put_mouse_event_opaque;
161

    
162
    if (mouse_event) {
163
        if (entry->qemu_put_mouse_event_absolute) {
164
            width = 0x7fff;
165
            height = 0x7fff;
166
        } else {
167
            width = graphic_width - 1;
168
            height = graphic_height - 1;
169
        }
170

    
171
        switch (graphic_rotate) {
172
        case 0:
173
            mouse_event(mouse_event_opaque,
174
                        dx, dy, dz, buttons_state);
175
            break;
176
        case 90:
177
            mouse_event(mouse_event_opaque,
178
                        width - dy, dx, dz, buttons_state);
179
            break;
180
        case 180:
181
            mouse_event(mouse_event_opaque,
182
                        width - dx, height - dy, dz, buttons_state);
183
            break;
184
        case 270:
185
            mouse_event(mouse_event_opaque,
186
                        dy, height - dx, dz, buttons_state);
187
            break;
188
        }
189
    }
190
}
191

    
192
int kbd_mouse_is_absolute(void)
193
{
194
    if (QTAILQ_EMPTY(&mouse_handlers)) {
195
        return 0;
196
    }
197

    
198
    return QTAILQ_FIRST(&mouse_handlers)->qemu_put_mouse_event_absolute;
199
}
200

    
201
int kbd_mouse_has_absolute(void)
202
{
203
    QEMUPutMouseEntry *entry;
204

    
205
    QTAILQ_FOREACH(entry, &mouse_handlers, node) {
206
        if (entry->qemu_put_mouse_event_absolute) {
207
            return 1;
208
        }
209
    }
210

    
211
    return 0;
212
}
213

    
214
static void info_mice_iter(QObject *data, void *opaque)
215
{
216
    QDict *mouse;
217
    Monitor *mon = opaque;
218

    
219
    mouse = qobject_to_qdict(data);
220
    monitor_printf(mon, "%c Mouse #%" PRId64 ": %s%s\n",
221
                  (qdict_get_bool(mouse, "current") ? '*' : ' '),
222
                   qdict_get_int(mouse, "index"), qdict_get_str(mouse, "name"),
223
                   qdict_get_bool(mouse, "absolute") ? " (absolute)" : "");
224
}
225

    
226
void do_info_mice_print(Monitor *mon, const QObject *data)
227
{
228
    QList *mice_list;
229

    
230
    mice_list = qobject_to_qlist(data);
231
    if (qlist_empty(mice_list)) {
232
        monitor_printf(mon, "No mouse devices connected\n");
233
        return;
234
    }
235

    
236
    qlist_iter(mice_list, info_mice_iter, mon);
237
}
238

    
239
void do_info_mice(Monitor *mon, QObject **ret_data)
240
{
241
    QEMUPutMouseEntry *cursor;
242
    QList *mice_list;
243
    int current;
244

    
245
    mice_list = qlist_new();
246

    
247
    if (QTAILQ_EMPTY(&mouse_handlers)) {
248
        goto out;
249
    }
250

    
251
    current = QTAILQ_FIRST(&mouse_handlers)->index;
252

    
253
    QTAILQ_FOREACH(cursor, &mouse_handlers, node) {
254
        QObject *obj;
255
        obj = qobject_from_jsonf("{ 'name': %s,"
256
                                 "  'index': %d,"
257
                                 "  'current': %i,"
258
                                 "  'absolute': %i }",
259
                                 cursor->qemu_put_mouse_event_name,
260
                                 cursor->index,
261
                                 cursor->index == current,
262
                                 !!cursor->qemu_put_mouse_event_absolute);
263
        qlist_append_obj(mice_list, obj);
264
    }
265

    
266
out:
267
    *ret_data = QOBJECT(mice_list);
268
}
269

    
270
void do_mouse_set(Monitor *mon, const QDict *qdict)
271
{
272
    QEMUPutMouseEntry *cursor;
273
    int index = qdict_get_int(qdict, "index");
274
    int found = 0;
275

    
276
    if (QTAILQ_EMPTY(&mouse_handlers)) {
277
        monitor_printf(mon, "No mouse devices connected\n");
278
        return;
279
    }
280

    
281
    QTAILQ_FOREACH(cursor, &mouse_handlers, node) {
282
        if (cursor->index == index) {
283
            found = 1;
284
            qemu_activate_mouse_event_handler(cursor);
285
            break;
286
        }
287
    }
288

    
289
    if (!found) {
290
        monitor_printf(mon, "Mouse at given index not found\n");
291
    }
292

    
293
    check_mode_change();
294
}
295

    
296
void qemu_add_mouse_mode_change_notifier(Notifier *notify)
297
{
298
    notifier_list_add(&mouse_mode_notifiers, notify);
299
}
300

    
301
void qemu_remove_mouse_mode_change_notifier(Notifier *notify)
302
{
303
    notifier_list_remove(&mouse_mode_notifiers, notify);
304
}