• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/sysemu.h"
26 #include "net/net.h"
27 #include "monitor/monitor.h"
28 #include "ui/console.h"
29 #include "qapi/qmp/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 
qemu_add_kbd_event_handler(QEMUPutKBDEvent * func,void * opaque)46 void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
47 {
48     QEMUPutKBDEntry *s;
49 
50     if (func != NULL) {
51         s = g_malloc0(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 
qemu_remove_kbd_event_handler(QEMUPutKBDEvent * func,void * opaque)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 
check_mode_change(void)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, NULL);
84     }
85 
86     current_is_absolute = is_absolute;
87     current_has_absolute = has_absolute;
88 }
89 
qemu_add_mouse_event_handler(QEMUPutMouseEvent * func,void * opaque,int absolute,const char * name)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 = g_malloc0(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 = g_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 
qemu_activate_mouse_event_handler(QEMUPutMouseEntry * entry)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 
qemu_remove_mouse_event_handler(QEMUPutMouseEntry * entry)120 void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry)
121 {
122     QTAILQ_REMOVE(&mouse_handlers, entry, node);
123 
124     g_free(entry->qemu_put_mouse_event_name);
125     g_free(entry);
126 
127     check_mode_change();
128 }
129 
qemu_add_led_event_handler(QEMUPutLEDEvent * func,void * opaque)130 QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func,
131                                             void *opaque)
132 {
133     QEMUPutLEDEntry *s;
134 
135     s = g_malloc0(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 
qemu_remove_led_event_handler(QEMUPutLEDEntry * entry)143 void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
144 {
145     if (entry == NULL)
146         return;
147     QTAILQ_REMOVE(&led_handlers, entry, next);
148     g_free(entry);
149 }
150 
kbd_put_keycode(int keycode)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 
kbd_put_ledstate(int ledstate)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 
kbd_mouse_event(int dx,int dy,int dz,int buttons_state)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 
kbd_mouse_is_absolute(void)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 
kbd_mouse_has_absolute(void)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 
info_mice_iter(QObject * data,void * opaque)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 
do_info_mice_print(Monitor * mon,const QObject * data)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 
do_info_mice(Monitor * mon,QObject ** ret_data)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 
do_mouse_set(Monitor * mon,const QDict * qdict)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 
qemu_add_mouse_mode_change_notifier(Notifier * notify)308 void qemu_add_mouse_mode_change_notifier(Notifier *notify)
309 {
310     notifier_list_add(&mouse_mode_notifiers, notify);
311 }
312 
qemu_remove_mouse_mode_change_notifier(Notifier * notify)313 void qemu_remove_mouse_mode_change_notifier(Notifier *notify)
314 {
315     notifier_remove(notify);
316 }
317