blob: 9e8835679e7fe4e1fd0db7630ce1a4538fdb747d [file] [log] [blame]
Vladimir Chtchetkine01193622010-05-11 13:07:22 -07001/* Copyright (C) 2006-2010 The Android Open Source Project
2**
3** This software is licensed under the terms of the GNU General Public
4** License version 2, as published by the Free Software Foundation, and
5** may be copied, distributed, and modified under those terms.
6**
7** This program is distributed in the hope that it will be useful,
8** but WITHOUT ANY WARRANTY; without even the implied warranty of
9** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10** GNU General Public License for more details.
11*/
12
Vladimir Chtchetkine01193622010-05-11 13:07:22 -070013#include "android/utils/debug.h"
14#include "android/utils/bufprint.h"
15#include "android/globals.h"
16#include "android/qemulator.h"
Vladimir Chtchetkine777eb682011-01-26 11:19:19 -080017#include "android/protocol/core-commands-api.h"
18#include "android/protocol/ui-commands-api.h"
David 'Digit' Turner055ae422010-07-27 11:34:16 -070019#include "user-events.h"
Vladimir Chtchetkine01193622010-05-11 13:07:22 -070020
21#define D(...) do { if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0)
22static double get_default_scale( AndroidOptions* opts );
23
24/* QEmulator structure instance. */
25static QEmulator qemulator[1];
26
David 'Digit' Turner055ae422010-07-27 11:34:16 -070027static void handle_key_command( void* opaque, SkinKeyCommand command, int param );
28static void qemulator_refresh(QEmulator* emulator);
Vladimir Chtchetkine6b985d72011-01-20 18:02:35 -080029extern void qemu_system_shutdown_request(void);
David 'Digit' Turner055ae422010-07-27 11:34:16 -070030
Vladimir Chtchetkine01193622010-05-11 13:07:22 -070031static void
32qemulator_light_brightness( void* opaque, const char* light, int value )
33{
34 QEmulator* emulator = opaque;
35
36 VERBOSE_PRINT(hw_control,"%s: light='%s' value=%d window=%p", __FUNCTION__, light, value, emulator->window);
37 if ( !strcmp(light, "lcd_backlight") ) {
38 emulator->lcd_brightness = value;
39 if (emulator->window)
40 skin_window_set_lcd_brightness( emulator->window, value );
41 return;
42 }
43}
44
45static void
46qemulator_setup( QEmulator* emulator )
47{
48 AndroidOptions* opts = emulator->opts;
49
50 if ( !emulator->window && !opts->no_window ) {
51 SkinLayout* layout = emulator->layout;
52 double scale = get_default_scale(emulator->opts);
53
54 emulator->window = skin_window_create( layout, emulator->win_x, emulator->win_y, scale, 0);
55 if (emulator->window == NULL)
56 return;
57
58 {
59 SkinTrackBall* ball;
60 SkinTrackBallParameters params;
61
62 params.diameter = 30;
63 params.ring = 2;
64 params.ball_color = 0xffe0e0e0;
65 params.dot_color = 0xff202020;
66 params.ring_color = 0xff000000;
67
68 ball = skin_trackball_create( &params );
69 emulator->trackball = ball;
70 skin_window_set_trackball( emulator->window, ball );
71
72 emulator->lcd_brightness = 128; /* 50% */
73 skin_window_set_lcd_brightness( emulator->window, emulator->lcd_brightness );
74 }
75
76 if ( emulator->onion != NULL )
77 skin_window_set_onion( emulator->window,
78 emulator->onion,
79 emulator->onion_rotation,
80 emulator->onion_alpha );
81
82 qemulator_set_title(emulator);
83
84 skin_window_enable_touch ( emulator->window, android_hw->hw_touchScreen != 0 );
85 skin_window_enable_dpad ( emulator->window, android_hw->hw_dPad != 0 );
86 skin_window_enable_qwerty( emulator->window, android_hw->hw_keyboard != 0 );
87 skin_window_enable_trackball( emulator->window, android_hw->hw_trackBall != 0 );
88 }
89
90 /* initialize hardware control support */
Vladimir Chtchetkine777eb682011-01-26 11:19:19 -080091 uicmd_set_brightness_change_callback(qemulator_light_brightness,
92 emulator);
Vladimir Chtchetkine01193622010-05-11 13:07:22 -070093}
94
95static void
96qemulator_fb_update( void* _emulator, int x, int y, int w, int h )
97{
98 QEmulator* emulator = _emulator;
99
David 'Digit' Turner07db3492011-02-02 17:36:34 +0100100 if (!emulator->window) {
David 'Digit' Turnera1dcb6c2011-02-09 17:32:56 +0100101 if (emulator->opts->no_window)
102 return;
David 'Digit' Turner07db3492011-02-02 17:36:34 +0100103 qemulator_setup( emulator );
104 }
105 skin_window_update_display( emulator->window, x, y, w, h );
Vladimir Chtchetkine01193622010-05-11 13:07:22 -0700106}
107
108static void
109qemulator_fb_rotate( void* _emulator, int rotation )
110{
David 'Digit' Turner055ae422010-07-27 11:34:16 -0700111 QEmulator* emulator = _emulator;
Vladimir Chtchetkine01193622010-05-11 13:07:22 -0700112
113 qemulator_setup( emulator );
114}
115
David 'Digit' Turner055ae422010-07-27 11:34:16 -0700116static void
117qemulator_fb_poll( void* _emulator )
118{
119 QEmulator* emulator = _emulator;
120 qemulator_refresh(emulator);
121}
122
Vladimir Chtchetkine01193622010-05-11 13:07:22 -0700123QEmulator*
124qemulator_get(void)
125{
126 return qemulator;
127}
128
129int
130qemulator_init( QEmulator* emulator,
131 AConfig* aconfig,
132 const char* basepath,
133 int x,
134 int y,
135 AndroidOptions* opts )
136{
137 emulator->aconfig = aconfig;
138 emulator->layout_file = skin_file_create_from_aconfig(aconfig, basepath);
139 emulator->layout = emulator->layout_file->layouts;
140 // If we have a custom charmap use it to initialize keyboard.
141 // Otherwise initialize keyboard from configuration settings.
142 // Another way to configure keyboard to use a custom charmap would
143 // be saving a custom charmap name into AConfig's keyboard->charmap
144 // property, and calling single skin_keyboard_create_from_aconfig
145 // routine to initialize keyboard.
146 if (NULL != opts->charmap) {
147 emulator->keyboard = skin_keyboard_create_from_kcm(opts->charmap, opts->raw_keys);
148 } else {
149 emulator->keyboard = skin_keyboard_create_from_aconfig(aconfig, opts->raw_keys);
150 }
151 emulator->window = NULL;
152 emulator->win_x = x;
153 emulator->win_y = y;
154 emulator->opts[0] = opts[0];
155
156 /* register as a framebuffer clients for all displays defined in the skin file */
157 SKIN_FILE_LOOP_PARTS( emulator->layout_file, part )
158 SkinDisplay* disp = part->display;
159 if (disp->valid) {
160 qframebuffer_add_client( disp->qfbuff,
David 'Digit' Turner055ae422010-07-27 11:34:16 -0700161 emulator,
162 qemulator_fb_update,
163 qemulator_fb_rotate,
164 qemulator_fb_poll,
165 NULL );
Vladimir Chtchetkine01193622010-05-11 13:07:22 -0700166 }
167 SKIN_FILE_LOOP_END_PARTS
David 'Digit' Turner055ae422010-07-27 11:34:16 -0700168
169 skin_keyboard_enable( emulator->keyboard, 1 );
170 skin_keyboard_on_command( emulator->keyboard, handle_key_command, emulator );
171
Vladimir Chtchetkine01193622010-05-11 13:07:22 -0700172 return 0;
173}
174
175void
176qemulator_done(QEmulator* emulator)
177{
178 if (emulator->window) {
179 skin_window_free(emulator->window);
180 emulator->window = NULL;
181 }
182 if (emulator->trackball) {
183 skin_trackball_destroy(emulator->trackball);
184 emulator->trackball = NULL;
185 }
186 if (emulator->keyboard) {
187 skin_keyboard_free(emulator->keyboard);
188 emulator->keyboard = NULL;
189 }
190 emulator->layout = NULL;
191 if (emulator->layout_file) {
192 skin_file_free(emulator->layout_file);
193 emulator->layout_file = NULL;
194 }
195}
196
197SkinLayout*
198qemulator_get_layout(QEmulator* emulator)
199{
200 return emulator->layout;
201}
202
Vladimir Chtchetkinecf755ea2011-01-12 14:38:19 -0800203QFrameBuffer*
204qemulator_get_first_framebuffer(QEmulator* emulator)
205{
206 /* register as a framebuffer clients for all displays defined in the skin file */
207 SKIN_FILE_LOOP_PARTS( emulator->layout_file, part )
208 SkinDisplay* disp = part->display;
209 if (disp->valid) {
210 return disp->qfbuff;
211 }
212 SKIN_FILE_LOOP_END_PARTS
213 return NULL;
214}
215
Vladimir Chtchetkine01193622010-05-11 13:07:22 -0700216void
217qemulator_set_title(QEmulator* emulator)
218{
219 char temp[128], *p=temp, *end=p+sizeof temp;;
220
221 if (emulator->window == NULL)
222 return;
223
224 if (emulator->show_trackball) {
225 SkinKeyBinding bindings[ SKIN_KEY_COMMAND_MAX_BINDINGS ];
226 int count;
227
228 count = skin_keyset_get_bindings( android_keyset,
229 SKIN_KEY_COMMAND_TOGGLE_TRACKBALL,
230 bindings );
231
232 if (count > 0) {
233 int nn;
234 p = bufprint( p, end, "Press " );
235 for (nn = 0; nn < count; nn++) {
236 if (nn > 0) {
237 if (nn < count-1)
238 p = bufprint(p, end, ", ");
239 else
240 p = bufprint(p, end, " or ");
241 }
242 p = bufprint(p, end, "%s",
243 skin_key_symmod_to_str( bindings[nn].sym,
244 bindings[nn].mod ) );
245 }
246 p = bufprint(p, end, " to leave trackball mode. ");
247 }
248 }
249
250 p = bufprint(p, end, "%d:%s",
Vladimir Chtchetkine57584042011-01-20 16:15:30 -0800251 android_base_port,
Vladimir Chtchetkine01193622010-05-11 13:07:22 -0700252 avdInfo_getName( android_avdInfo ));
253
254 skin_window_set_title( emulator->window, temp );
255}
256
257/*
258 * Helper routines
259 */
260
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100261static int
Vladimir Chtchetkine01193622010-05-11 13:07:22 -0700262get_device_dpi( AndroidOptions* opts )
263{
Vladimir Chtchetkine777eb682011-01-26 11:19:19 -0800264 int dpi_device = corecmd_get_hw_lcd_density();
Vladimir Chtchetkine01193622010-05-11 13:07:22 -0700265
266 if (opts->dpi_device != NULL) {
267 char* end;
268 dpi_device = strtol( opts->dpi_device, &end, 0 );
269 if (end == NULL || *end != 0 || dpi_device <= 0) {
270 fprintf(stderr, "argument for -dpi-device must be a positive integer. Aborting\n" );
271 exit(1);
272 }
273 }
274 return dpi_device;
275}
276
277static double
278get_default_scale( AndroidOptions* opts )
279{
280 int dpi_device = get_device_dpi( opts );
281 int dpi_monitor = -1;
282 double scale = 0.0;
283
284 /* possible values for the 'scale' option are
285 * 'auto' : try to determine the scale automatically
286 * '<number>dpi' : indicates the host monitor dpi, compute scale accordingly
287 * '<fraction>' : use direct scale coefficient
288 */
289
290 if (opts->scale) {
291 if (!strcmp(opts->scale, "auto"))
292 {
293 /* we need to get the host dpi resolution ? */
294 int xdpi, ydpi;
295
296 if ( SDL_WM_GetMonitorDPI( &xdpi, &ydpi ) < 0 ) {
297 fprintf(stderr, "could not get monitor DPI resolution from system. please use -dpi-monitor to specify one\n" );
298 exit(1);
299 }
300 D( "system reported monitor resolutions: xdpi=%d ydpi=%d\n", xdpi, ydpi);
301 dpi_monitor = (xdpi + ydpi+1)/2;
302 }
303 else
304 {
305 char* end;
306 scale = strtod( opts->scale, &end );
307
308 if (end && end[0] == 'd' && end[1] == 'p' && end[2] == 'i' && end[3] == 0) {
309 if ( scale < 20 || scale > 1000 ) {
310 fprintf(stderr, "emulator: ignoring bad -scale argument '%s': %s\n", opts->scale,
311 "host dpi number must be between 20 and 1000" );
312 exit(1);
313 }
314 dpi_monitor = scale;
315 scale = 0.0;
316 }
317 else if (end == NULL || *end != 0) {
318 fprintf(stderr, "emulator: ignoring bad -scale argument '%s': %s\n", opts->scale,
319 "not a number or the 'auto' keyword" );
320 exit(1);
321 }
322 else if ( scale < 0.1 || scale > 3. ) {
323 fprintf(stderr, "emulator: ignoring bad -window-scale argument '%s': %s\n", opts->scale,
324 "must be between 0.1 and 3.0" );
325 exit(1);
326 }
327 }
328 }
329
330 if (scale == 0.0 && dpi_monitor > 0)
331 scale = dpi_monitor*1.0/dpi_device;
332
Vladimir Chtchetkine01193622010-05-11 13:07:22 -0700333 return scale;
334}
335
David 'Digit' Turner055ae422010-07-27 11:34:16 -0700336/* used to respond to a given keyboard command shortcut
337 */
338static void
339handle_key_command( void* opaque, SkinKeyCommand command, int down )
340{
341 static const struct { SkinKeyCommand cmd; AndroidKeyCode kcode; } keycodes[] =
342 {
Maciek Molerus97d15562011-07-06 12:27:56 +0200343 { SKIN_KEY_COMMAND_BUTTON_CALL, kKeyCodeCall },
344 { SKIN_KEY_COMMAND_BUTTON_HOME, kKeyCodeHome },
345 { SKIN_KEY_COMMAND_BUTTON_BACK, kKeyCodeBack },
346 { SKIN_KEY_COMMAND_BUTTON_HANGUP, kKeyCodeEndCall },
347 { SKIN_KEY_COMMAND_BUTTON_POWER, kKeyCodePower },
David 'Digit' Turner055ae422010-07-27 11:34:16 -0700348 { SKIN_KEY_COMMAND_BUTTON_SEARCH, kKeyCodeSearch },
349 { SKIN_KEY_COMMAND_BUTTON_MENU, kKeyCodeMenu },
350 { SKIN_KEY_COMMAND_BUTTON_DPAD_UP, kKeyCodeDpadUp },
351 { SKIN_KEY_COMMAND_BUTTON_DPAD_LEFT, kKeyCodeDpadLeft },
352 { SKIN_KEY_COMMAND_BUTTON_DPAD_RIGHT, kKeyCodeDpadRight },
353 { SKIN_KEY_COMMAND_BUTTON_DPAD_DOWN, kKeyCodeDpadDown },
354 { SKIN_KEY_COMMAND_BUTTON_DPAD_CENTER, kKeyCodeDpadCenter },
355 { SKIN_KEY_COMMAND_BUTTON_VOLUME_UP, kKeyCodeVolumeUp },
356 { SKIN_KEY_COMMAND_BUTTON_VOLUME_DOWN, kKeyCodeVolumeDown },
357 { SKIN_KEY_COMMAND_BUTTON_CAMERA, kKeyCodeCamera },
Maciek Molerus97d15562011-07-06 12:27:56 +0200358 { SKIN_KEY_COMMAND_BUTTON_TV, kKeyCodeTV },
359 { SKIN_KEY_COMMAND_BUTTON_EPG, kKeyCodeEPG },
360 { SKIN_KEY_COMMAND_BUTTON_DVR, kKeyCodeDVR },
361 { SKIN_KEY_COMMAND_BUTTON_PREV, kKeyCodePrevious },
362 { SKIN_KEY_COMMAND_BUTTON_NEXT, kKeyCodeNext },
363 { SKIN_KEY_COMMAND_BUTTON_PLAY, kKeyCodePlay },
364 { SKIN_KEY_COMMAND_BUTTON_PAUSE, kKeyCodePause },
365 { SKIN_KEY_COMMAND_BUTTON_STOP, kKeyCodeStop },
366 { SKIN_KEY_COMMAND_BUTTON_REWIND, kKeyCodeRewind },
367 { SKIN_KEY_COMMAND_BUTTON_FFWD, kKeyCodeFastForward },
368 { SKIN_KEY_COMMAND_BUTTON_BOOKMARKS, kKeyCodeBookmarks },
369 { SKIN_KEY_COMMAND_BUTTON_WINDOW, kKeyCodeCycleWindows },
370 { SKIN_KEY_COMMAND_BUTTON_CHANNELUP, kKeyCodeChannelUp },
371 { SKIN_KEY_COMMAND_BUTTON_CHANNELDOWN, kKeyCodeChannelDown },
David 'Digit' Turner055ae422010-07-27 11:34:16 -0700372 { SKIN_KEY_COMMAND_NONE, 0 }
373 };
374 int nn;
375#ifdef CONFIG_TRACE
376 static int tracing = 0;
377#endif
378 QEmulator* emulator = opaque;
379
380
381 for (nn = 0; keycodes[nn].kcode != 0; nn++) {
382 if (command == keycodes[nn].cmd) {
383 unsigned code = keycodes[nn].kcode;
384 if (down)
385 code |= 0x200;
386 user_event_keycode( code );
387 return;
388 }
389 }
390
391 // for the show-trackball command, handle down events to enable, and
392 // up events to disable
393 if (command == SKIN_KEY_COMMAND_SHOW_TRACKBALL) {
394 emulator->show_trackball = (down != 0);
395 skin_window_show_trackball( emulator->window, emulator->show_trackball );
396 //qemulator_set_title( emulator );
397 return;
398 }
399
400 // only handle down events for the rest
401 if (down == 0)
402 return;
403
404 switch (command)
405 {
406 case SKIN_KEY_COMMAND_TOGGLE_NETWORK:
407 {
Vladimir Chtchetkine777eb682011-01-26 11:19:19 -0800408 corecmd_toggle_network();
409 D( "network is now %s", corecmd_is_network_disabled() ?
Vladimir Chtchetkinecefa7442010-09-01 09:17:11 -0700410 "disconnected" : "connected" );
David 'Digit' Turner055ae422010-07-27 11:34:16 -0700411 }
412 break;
413
414 case SKIN_KEY_COMMAND_TOGGLE_FULLSCREEN:
415 if (emulator->window) {
416 skin_window_toggle_fullscreen(emulator->window);
417 }
418 break;
419
420 case SKIN_KEY_COMMAND_TOGGLE_TRACING:
421 {
422#ifdef CONFIG_TRACE
423 tracing = !tracing;
Vladimir Chtchetkine777eb682011-01-26 11:19:19 -0800424 corecmd_trace_control(tracing);
David 'Digit' Turner055ae422010-07-27 11:34:16 -0700425#endif
426 }
427 break;
428
429 case SKIN_KEY_COMMAND_TOGGLE_TRACKBALL:
430 emulator->show_trackball = !emulator->show_trackball;
431 skin_window_show_trackball( emulator->window, emulator->show_trackball );
432 qemulator_set_title(emulator);
433 break;
434
435 case SKIN_KEY_COMMAND_ONION_ALPHA_UP:
436 case SKIN_KEY_COMMAND_ONION_ALPHA_DOWN:
437 if (emulator->onion)
438 {
439 int alpha = emulator->onion_alpha;
440
441 if (command == SKIN_KEY_COMMAND_ONION_ALPHA_UP)
442 alpha += 16;
443 else
444 alpha -= 16;
445
446 if (alpha > 256)
447 alpha = 256;
448 else if (alpha < 0)
449 alpha = 0;
450
451 emulator->onion_alpha = alpha;
452 skin_window_set_onion( emulator->window, emulator->onion, emulator->onion_rotation, alpha );
453 skin_window_redraw( emulator->window, NULL );
454 //dprint( "onion alpha set to %d (%.f %%)", alpha, alpha/2.56 );
455 }
456 break;
457
458 case SKIN_KEY_COMMAND_CHANGE_LAYOUT_PREV:
459 case SKIN_KEY_COMMAND_CHANGE_LAYOUT_NEXT:
460 {
461 SkinLayout* layout = NULL;
462
463 if (command == SKIN_KEY_COMMAND_CHANGE_LAYOUT_NEXT) {
464 layout = emulator->layout->next;
465 if (layout == NULL)
466 layout = emulator->layout_file->layouts;
467 }
468 else if (command == SKIN_KEY_COMMAND_CHANGE_LAYOUT_PREV) {
469 layout = emulator->layout_file->layouts;
470 while (layout->next && layout->next != emulator->layout)
471 layout = layout->next;
472 }
473 if (layout != NULL) {
474 SkinRotation rotation;
475
476 emulator->layout = layout;
477 skin_window_reset( emulator->window, layout );
478
479 rotation = skin_layout_get_dpad_rotation( layout );
480
481 if (emulator->keyboard)
482 skin_keyboard_set_rotation( emulator->keyboard, rotation );
483
484 if (emulator->trackball) {
485 skin_trackball_set_rotation( emulator->trackball, rotation );
486 skin_window_set_trackball( emulator->window, emulator->trackball );
487 skin_window_show_trackball( emulator->window, emulator->show_trackball );
488 }
489
490 skin_window_set_lcd_brightness( emulator->window, emulator->lcd_brightness );
491
492 qframebuffer_invalidate_all();
493 qframebuffer_check_updates();
494 }
495 }
496 break;
497
498 default:
499 /* XXX: TODO ? */
500 ;
501 }
502}
503
504/* called periodically to poll for user input events */
505static void qemulator_refresh(QEmulator* emulator)
506{
507 SDL_Event ev;
508 SkinWindow* window = emulator->window;
509 SkinKeyboard* keyboard = emulator->keyboard;
510
511 /* this will eventually call sdl_update if the content of the VGA framebuffer
512 * has changed */
513 qframebuffer_check_updates();
514
515 if (window == NULL)
516 return;
517
518 while(SDL_PollEvent(&ev)){
519 switch(ev.type){
520 case SDL_VIDEOEXPOSE:
521 skin_window_redraw( window, NULL );
522 break;
523
524 case SDL_KEYDOWN:
525#ifdef _WIN32
526 /* special code to deal with Alt-F4 properly */
527 if (ev.key.keysym.sym == SDLK_F4 &&
528 ev.key.keysym.mod & KMOD_ALT) {
529 goto CleanExit;
530 }
531#endif
532#ifdef __APPLE__
533 /* special code to deal with Command-Q properly */
534 if (ev.key.keysym.sym == SDLK_q &&
535 ev.key.keysym.mod & KMOD_META) {
536 goto CleanExit;
537 }
538#endif
539 skin_keyboard_process_event( keyboard, &ev, 1 );
540 break;
541
542 case SDL_KEYUP:
543 skin_keyboard_process_event( keyboard, &ev, 0 );
544 break;
545
546 case SDL_MOUSEMOTION:
547 skin_window_process_event( window, &ev );
548 break;
549
550 case SDL_MOUSEBUTTONDOWN:
551 case SDL_MOUSEBUTTONUP:
552 {
553 int down = (ev.type == SDL_MOUSEBUTTONDOWN);
554 if (ev.button.button == 4)
555 {
556 /* scroll-wheel simulates DPad up */
557 AndroidKeyCode kcode;
558
559 kcode = // qemulator_rotate_keycode(kKeyCodeDpadUp);
560 android_keycode_rotate(kKeyCodeDpadUp,
561 skin_layout_get_dpad_rotation(qemulator_get_layout(qemulator_get())));
562 user_event_key( kcode, down );
563 }
564 else if (ev.button.button == 5)
565 {
566 /* scroll-wheel simulates DPad down */
567 AndroidKeyCode kcode;
568
569 kcode = // qemulator_rotate_keycode(kKeyCodeDpadDown);
570 android_keycode_rotate(kKeyCodeDpadDown,
571 skin_layout_get_dpad_rotation(qemulator_get_layout(qemulator_get())));
572 user_event_key( kcode, down );
573 }
574 else if (ev.button.button == SDL_BUTTON_LEFT) {
575 skin_window_process_event( window, &ev );
576 }
577#if 0
578 else {
579 fprintf(stderr, "... mouse button %s: button=%d state=%04x x=%d y=%d\n",
580 down ? "down" : "up ",
581 ev.button.button, ev.button.state, ev.button.x, ev.button.y);
582 }
583#endif
584 }
585 break;
586
587 case SDL_QUIT:
588#if defined _WIN32 || defined __APPLE__
589 CleanExit:
590#endif
591 /* only save emulator config through clean exit */
592 qemulator_done(qemulator_get());
Vladimir Chtchetkine6b985d72011-01-20 18:02:35 -0800593 qemu_system_shutdown_request();
David 'Digit' Turner055ae422010-07-27 11:34:16 -0700594 return;
595 }
596 }
597
598 skin_keyboard_flush( keyboard );
599}
600
Vladimir Chtchetkine01193622010-05-11 13:07:22 -0700601/*
602 * android/console.c helper routines.
603 */
604
605SkinKeyboard*
606android_emulator_get_keyboard(void)
607{
608 return qemulator->keyboard;
609}
610
611void
612android_emulator_set_window_scale( double scale, int is_dpi )
613{
614 QEmulator* emulator = qemulator;
615
616 if (is_dpi)
617 scale /= get_device_dpi( emulator->opts );
618
619 if (emulator->window)
620 skin_window_set_scale( emulator->window, scale );
621}
622
David 'Digit' Turner3cf34f22010-07-30 16:53:39 -0700623
624void
625android_emulator_set_base_port( int port )
626{
Vladimir Chtchetkinecefa7442010-09-01 09:17:11 -0700627 /* Base port is already set in the emulator's core. */
David 'Digit' Turner3cf34f22010-07-30 16:53:39 -0700628 qemulator_set_title(qemulator);
629}