static void qemulator_setup( QEmulator* emulator ) { AndroidOptions* opts = emulator->opts; if ( !emulator->window && !opts->no_window ) { SkinLayout* layout = emulator->layout; double scale = get_default_scale(emulator->opts); static const SkinWindowFuncs skin_window_funcs = { .key_event = &qemulator_window_key_event, .mouse_event = &qemulator_window_mouse_event, .generic_event = &qemulator_window_generic_event, .opengles_show = &android_showOpenglesWindow, .opengles_hide = &android_hideOpenglesWindow, .opengles_redraw = &android_redrawOpenglesWindow, }; emulator->window = skin_window_create(layout, emulator->win_x, emulator->win_y, scale, 0, &skin_window_funcs); if (emulator->window == NULL) return; { SkinTrackBall* ball; SkinTrackBallParameters params; params.diameter = 30; params.ring = 2; params.ball_color = 0xffe0e0e0; params.dot_color = 0xff202020; params.ring_color = 0xff000000; params.event_func = &qemulator_trackball_event; ball = skin_trackball_create( ¶ms ); emulator->trackball = ball; skin_window_set_trackball( emulator->window, ball ); emulator->lcd_brightness = 128; /* 50% */ skin_window_set_lcd_brightness( emulator->window, emulator->lcd_brightness ); } if ( emulator->onion != NULL ) skin_window_set_onion( emulator->window, emulator->onion, emulator->onion_rotation, emulator->onion_alpha ); qemulator_set_title(emulator); skin_window_enable_touch ( emulator->window, !androidHwConfig_isScreenNoTouch(android_hw)); skin_window_enable_dpad ( emulator->window, android_hw->hw_dPad != 0 ); skin_window_enable_qwerty( emulator->window, android_hw->hw_keyboard != 0 ); skin_window_enable_trackball( emulator->window, android_hw->hw_trackBall != 0 ); }
static void qemulator_setup( QEmulator* emulator ) { AndroidOptions* opts = emulator->opts; if ( !emulator->window && !opts->no_window ) { SkinLayout* layout = emulator->layout; double scale = get_default_scale(emulator->opts); emulator->window = skin_window_create( layout, emulator->win_x, emulator->win_y, scale, 0); if (emulator->window == NULL) return; { SkinTrackBall* ball; SkinTrackBallParameters params; params.diameter = 30; params.ring = 2; params.ball_color = 0xffe0e0e0; params.dot_color = 0xff202020; params.ring_color = 0xff000000; ball = skin_trackball_create( ¶ms ); emulator->trackball = ball; skin_window_set_trackball( emulator->window, ball ); emulator->lcd_brightness = 128; skin_window_set_lcd_brightness( emulator->window, emulator->lcd_brightness ); } if ( emulator->onion != NULL ) skin_window_set_onion( emulator->window, emulator->onion, emulator->onion_rotation, emulator->onion_alpha ); qemulator_set_title(emulator); skin_window_enable_touch ( emulator->window, !androidHwConfig_isScreenNoTouch(android_hw)); skin_window_enable_dpad ( emulator->window, android_hw->hw_dPad != 0 ); skin_window_enable_qwerty( emulator->window, android_hw->hw_keyboard != 0 ); skin_window_enable_trackball( emulator->window, android_hw->hw_trackBall != 0 ); } uicmd_set_brightness_change_callback(qemulator_light_brightness, emulator); }
static void emulator_window_setup( EmulatorWindow* emulator ) { static const SkinWindowFuncs my_window_funcs = { .key_event = &emulator_window_window_key_event, .mouse_event = &emulator_window_window_mouse_event, .generic_event = &emulator_window_window_generic_event, .opengles_show = &emulator_window_opengles_show_window, .opengles_hide = &emulator_window_opengles_hide_window, .opengles_redraw = &emulator_window_opengles_redraw_window, .opengles_free = &android_stopOpenglesRenderer, }; static const SkinTrackBallParameters my_trackball_params = { .diameter = 30, .ring = 2, .ball_color = 0xffe0e0e0, .dot_color = 0xff202020, .ring_color = 0xff000000, .event_func = &emulator_window_trackball_event, }; if (emulator->opts->no_window || emulator->ui) { return; } SkinUIParams my_ui_params = { .enable_touch = !androidHwConfig_isScreenNoTouch(android_hw), .enable_dpad = android_hw->hw_dPad != 0, .enable_keyboard = android_hw->hw_keyboard != 0, .enable_trackball = android_hw->hw_trackBall != 0, .window_x = emulator->win_x, .window_y = emulator->win_y, .window_scale = get_default_scale(emulator->opts), .keyboard_charmap = emulator->opts->charmap, .keyboard_raw_keys = emulator->opts->raw_keys != 0, #if CONFIG_QT .win32_ignore_events = true, #else .win32_ignore_events = false, #endif }; write_window_name(my_ui_params.window_name, sizeof(my_ui_params.window_name), android_base_port, avdInfo_getName(android_avdInfo)); static const SkinUIFuncs my_ui_funcs = { .window_funcs = &my_window_funcs, .trackball_params = &my_trackball_params, .keyboard_event = &emulator_window_keyboard_event, //user_event_key, .keyboard_flush = &user_event_keycodes, .network_toggle = &emulator_window_network_toggle, .framebuffer_invalidate = &emulator_window_framebuffer_invalidate, }; // Determine whether to use an EmuGL sub-window or not. const char* env = getenv("ANDROID_GL_SOFTWARE_RENDERER"); s_use_emugl_subwindow = !env || !env[0] || env[0] == '0'; if (s_use_emugl_subwindow) { VERBOSE_PRINT(gles, "Using EmuGL sub-window for GPU display"); } else { VERBOSE_PRINT(gles, "Using glReadPixels() for GPU display"); } emulator->ui = skin_ui_create(emulator->layout_file, android_hw->hw_initialOrientation, &my_ui_funcs, &my_ui_params); if (!emulator->ui) { return; } if (emulator->onion) { skin_ui_set_onion(emulator->ui, emulator->onion, emulator->onion_rotation, emulator->onion_alpha); } // Determine whether to use an EmuGL sub-window or not. if (!s_use_emugl_subwindow) { gpu_frame_set_post_callback(looper_newCore(), emulator, _emulator_window_on_gpu_frame); } skin_ui_reset_title(emulator->ui); } static void emulator_window_fb_update( void* _emulator, int x, int y, int w, int h ) { EmulatorWindow* emulator = _emulator; if (emulator->opts->no_window) { return; } if (!emulator->ui) { emulator_window_setup(emulator); } skin_ui_update_display(emulator->ui, x, y, w, h); } static void emulator_window_fb_rotate( void* _emulator, int rotation ) { EmulatorWindow* emulator = _emulator; emulator_window_setup( emulator ); }
void events_dev_init(uint32_t base, qemu_irq irq) { events_state *s; int iomemtype; AndroidHwConfig* config = android_hw; s = (events_state *) qemu_mallocz(sizeof(events_state)); /* now set the events capability bits depending on hardware configuration */ /* apparently, the EV_SYN array is used to indicate which other * event classes to consider. */ /* configure EV_KEY array * * All Android devices must have the following keys: * KEY_HOME, KEY_BACK, KEY_SEND (Call), KEY_END (EndCall), * KEY_SOFT1 (Menu), VOLUME_UP, VOLUME_DOWN * * Note that previous models also had a KEY_SOFT2, * and a KEY_POWER which we still support here. * * Newer models have a KEY_SEARCH key, which we always * enable here. * * A Dpad will send: KEY_DOWN / UP / LEFT / RIGHT / CENTER * * The KEY_CAMERA button isn't very useful if there is no camera. * * BTN_MOUSE is sent when the trackball is pressed * BTN_TOUCH is sent when the touchscreen is pressed */ events_set_bit (s, EV_SYN, EV_KEY ); events_set_bit(s, EV_KEY, KEY_HOME); events_set_bit(s, EV_KEY, KEY_BACK); events_set_bit(s, EV_KEY, KEY_SEND); events_set_bit(s, EV_KEY, KEY_END); events_set_bit(s, EV_KEY, KEY_SOFT1); events_set_bit(s, EV_KEY, KEY_VOLUMEUP); events_set_bit(s, EV_KEY, KEY_VOLUMEDOWN); events_set_bit(s, EV_KEY, KEY_SOFT2); events_set_bit(s, EV_KEY, KEY_POWER); events_set_bit(s, EV_KEY, KEY_SEARCH); if (config->hw_dPad) { events_set_bit(s, EV_KEY, KEY_DOWN); events_set_bit(s, EV_KEY, KEY_UP); events_set_bit(s, EV_KEY, KEY_LEFT); events_set_bit(s, EV_KEY, KEY_RIGHT); events_set_bit(s, EV_KEY, KEY_CENTER); } if (config->hw_trackBall) { events_set_bit(s, EV_KEY, BTN_MOUSE); } if (androidHwConfig_isScreenTouch(config)) { events_set_bit(s, EV_KEY, BTN_TOUCH); } if (strcmp(config->hw_camera_back, "none") || strcmp(config->hw_camera_front, "none")) { /* Camera emulation is enabled. */ events_set_bit(s, EV_KEY, KEY_CAMERA); } if (config->hw_keyboard) { /* since we want to implement Unicode reverse-mapping * allow any kind of key, even those not available on * the skin. * * the previous code did set the [1..0x1ff] range, but * we don't want to enable certain bits in the middle * of the range that are registered for mouse/trackball/joystick * events. * * see "linux_keycodes.h" for the list of events codes. */ events_set_bits(s, EV_KEY, 1, 0xff); events_set_bits(s, EV_KEY, 0x160, 0x1ff); /* If there is a keyboard, but no DPad, we need to clear the * corresponding bits. Doing this is simpler than trying to exclude * the DPad values from the ranges above. */ if (!config->hw_dPad) { events_clr_bit(s, EV_KEY, KEY_DOWN); events_clr_bit(s, EV_KEY, KEY_UP); events_clr_bit(s, EV_KEY, KEY_LEFT); events_clr_bit(s, EV_KEY, KEY_RIGHT); events_clr_bit(s, EV_KEY, KEY_CENTER); } } /* configure EV_REL array * * EV_REL events are sent when the trackball is moved */ if (config->hw_trackBall) { events_set_bit (s, EV_SYN, EV_REL ); events_set_bits(s, EV_REL, REL_X, REL_Y); } /* configure EV_ABS array. * * EV_ABS events are sent when the touchscreen is pressed */ if (!androidHwConfig_isScreenNoTouch(config)) { ABSEntry* abs_values; events_set_bit (s, EV_SYN, EV_ABS ); events_set_bits(s, EV_ABS, ABS_X, ABS_Z); /* Allocate the absinfo to report the min/max bounds for each * absolute dimension. The array must contain 3, or ABS_MAX tuples * of (min,max,fuzz,flat) 32-bit values. * * min and max are the bounds * fuzz corresponds to the device's fuziness, we set it to 0 * flat corresponds to the flat position for JOEYDEV devices, * we also set it to 0. * * There is no need to save/restore this array in a snapshot * since the values only depend on the hardware configuration. */ s->abs_info_count = androidHwConfig_isScreenMultiTouch(config) ? ABS_MAX * 4 : 3 * 4; const int abs_size = sizeof(uint32_t) * s->abs_info_count; s->abs_info = malloc(abs_size); memset(s->abs_info, 0, abs_size); abs_values = (ABSEntry*)s->abs_info; abs_values[ABS_X].max = config->hw_lcd_width-1; abs_values[ABS_Y].max = config->hw_lcd_height-1; abs_values[ABS_Z].max = 1; if (androidHwConfig_isScreenMultiTouch(config)) { /* * Setup multitouch. */ events_set_bit(s, EV_ABS, ABS_MT_SLOT); events_set_bit(s, EV_ABS, ABS_MT_POSITION_X); events_set_bit(s, EV_ABS, ABS_MT_POSITION_Y); events_set_bit(s, EV_ABS, ABS_MT_TRACKING_ID); events_set_bit(s, EV_ABS, ABS_MT_TOUCH_MAJOR); events_set_bit(s, EV_ABS, ABS_MT_PRESSURE); abs_values[ABS_MT_SLOT].max = multitouch_get_max_slot(); abs_values[ABS_MT_TRACKING_ID].max = abs_values[ABS_MT_SLOT].max + 1; abs_values[ABS_MT_POSITION_X].max = abs_values[ABS_X].max; abs_values[ABS_MT_POSITION_Y].max = abs_values[ABS_Y].max; abs_values[ABS_MT_TOUCH_MAJOR].max = 0x7fffffff; // TODO: Make it less random abs_values[ABS_MT_PRESSURE].max = 0x100; // TODO: Make it less random } } /* configure EV_SW array * * EV_SW events are sent to indicate that the keyboard lid * was closed or opened (done when we switch layouts through * KP-7 or KP-9). * * We only support this when hw.keyboard.lid is true. */ if (config->hw_keyboard && config->hw_keyboard_lid) { events_set_bit(s, EV_SYN, EV_SW); events_set_bit(s, EV_SW, 0); } iomemtype = cpu_register_io_memory(events_readfn, events_writefn, s); cpu_register_physical_memory(base, 0xfff, iomemtype); qemu_add_kbd_event_handler(events_put_keycode, s); qemu_add_mouse_event_handler(events_put_mouse, s, 1, "goldfish-events"); s->base = base; s->irq = irq; s->first = 0; s->last = 0; s->state = STATE_INIT; s->name = qemu_strdup(config->hw_keyboard_charmap); /* This function migh fire buffered events to the device, so * ensure that it is called after initialization is complete */ user_event_register_generic(s, events_put_generic); register_savevm( "events_state", 0, EVENTS_STATE_SAVE_VERSION, events_state_save, events_state_load, s ); }