static int _mouse_move(GRAPHICS_CONTROLLER *gc, unsigned x, unsigned y, GC_NAV_CMDS *cmds) { PG_DISPLAY_SET *s = gc->igs; BD_IG_PAGE *page = NULL; unsigned page_id = bd_psr_read(gc->regs, PSR_MENU_PAGE_ID); unsigned cur_btn_id = bd_psr_read(gc->regs, PSR_SELECTED_BUTTON_ID); unsigned new_btn_id = 0xffff; unsigned ii; gc->valid_mouse_position = 0; page = _find_page(&s->ics->interactive_composition, page_id); if (!page) { ERROR("_mouse_move(): unknown page #%d (have %d pages)\n", page_id, s->ics->interactive_composition.num_pages); return -1; } for (ii = 0; ii < page->num_bogs; ii++) { BD_IG_BOG *bog = &page->bog[ii]; unsigned valid_id = gc->enabled_button[ii]; BD_IG_BUTTON *button = _find_button_bog(bog, valid_id); if (!button) continue; if (x < button->x_pos || y < button->y_pos) continue; /* Check for SELECTED state object (button that can be selected) */ BD_PG_OBJECT *object = _find_object_for_button(s, button, BTN_SELECTED); if (!object) continue; if (x >= button->x_pos + object->width || y >= button->y_pos + object->height) continue; /* mouse is over button */ /* is button already selected? */ if (button->id == cur_btn_id) { gc->valid_mouse_position = 1; return 0; } new_btn_id = button->id; break; } if (new_btn_id != 0xffff) { bd_psr_write(gc->regs, PSR_SELECTED_BUTTON_ID, new_btn_id); _render_page(gc, -1, cmds); gc->valid_mouse_position = 1; } return gc->valid_mouse_position; }
static void _set_button_page(GRAPHICS_CONTROLLER *gc, uint32_t param) { unsigned page_flag = param & 0x80000000; unsigned effect_flag = param & 0x40000000; unsigned button_flag = param & 0x20000000; unsigned page_id = (param >> 16) & 0xff; unsigned button_id = param & 0xffff; unsigned bog_idx = 0; PG_DISPLAY_SET *s = gc->igs; BD_IG_PAGE *page = NULL; BD_IG_BUTTON *button = NULL; GC_TRACE("_set_button_page(0x%08x): page flag %d, id %d, effects %d button flag %d, id %d\n", param, !!page_flag, page_id, !!effect_flag, !!button_flag, button_id); /* 10.4.3.4 (D) */ if (!page_flag && !button_flag) { return; } if (page_flag) { /* current page --> command is ignored */ if (page_id == bd_psr_read(gc->regs, PSR_MENU_PAGE_ID)) { GC_TRACE(" page is current\n"); return; } page = _find_page(&s->ics->interactive_composition, page_id); /* invalid page --> command is ignored */ if (!page) { GC_TRACE(" page is invalid\n"); return; } /* page changes */ _select_page(gc, page_id); } else { /* page does not change */ page_id = bd_psr_read(gc->regs, PSR_MENU_PAGE_ID); page = _find_page(&s->ics->interactive_composition, page_id); if (!page) { GC_ERROR("_set_button_page(): PSR_MENU_PAGE_ID refers to unknown page %d\n", page_id); return; } } if (button_flag) { /* find correct button and overlap group */ button = _find_button_page(page, button_id, &bog_idx); if (!page_flag) { if (!button) { /* page not given, invalid button --> ignore command */ GC_TRACE(" button is invalid\n"); return; } if (button_id == bd_psr_read(gc->regs, PSR_SELECTED_BUTTON_ID)) { /* page not given, current button --> ignore command */ GC_TRACE(" button is current\n"); return; } } } if (button) { gc->bog_data[bog_idx].enabled_button = button_id; _select_button(gc, button_id); } _render_page(gc, 0xffff, NULL); /* auto action not triggered yet */ }
static int _user_input(GRAPHICS_CONTROLLER *gc, uint32_t key, GC_NAV_CMDS *cmds) { PG_DISPLAY_SET *s = gc->igs; BD_IG_PAGE *page = NULL; unsigned page_id = bd_psr_read(gc->regs, PSR_MENU_PAGE_ID); unsigned cur_btn_id = bd_psr_read(gc->regs, PSR_SELECTED_BUTTON_ID); unsigned new_btn_id = cur_btn_id; unsigned ii; int activated_btn_id = -1; if (s->ics->interactive_composition.ui_model == IG_UI_MODEL_POPUP && !gc->popup_visible) { GC_TRACE("_user_input(): popup menu not visible\n"); return -1; } if (!gc->ig_drawn) { GC_ERROR("_user_input(): menu not visible\n"); return -1; } GC_TRACE("_user_input(%d)\n", key); page = _find_page(&s->ics->interactive_composition, page_id); if (!page) { GC_ERROR("_user_input(): unknown page id %d (have %d pages)\n", page_id, s->ics->interactive_composition.num_pages); return -1; } if (key == BD_VK_MOUSE_ACTIVATE) { if (!gc->valid_mouse_position) { GC_TRACE("_user_input(): BD_VK_MOUSE_ACTIVATE outside of valid buttons\n"); return -1; } key = BD_VK_ENTER; } for (ii = 0; ii < page->num_bogs; ii++) { BD_IG_BOG *bog = &page->bog[ii]; unsigned valid_id = gc->bog_data[ii].enabled_button; BD_IG_BUTTON *button = _find_button_bog(bog, valid_id); if (!button) { continue; } /* numeric select */ if (VK_IS_NUMERIC(key)) { if (button->numeric_select_value == VK_TO_NUMBER(key)) { new_btn_id = button->id; } } /* cursor keys */ else if (VK_IS_CURSOR(key) || key == BD_VK_ENTER) { if (button->id == cur_btn_id) { switch(key) { case BD_VK_UP: new_btn_id = button->upper_button_id_ref; break; case BD_VK_DOWN: new_btn_id = button->lower_button_id_ref; break; case BD_VK_LEFT: new_btn_id = button->left_button_id_ref; break; case BD_VK_RIGHT: new_btn_id = button->right_button_id_ref; break; case BD_VK_ENTER: activated_btn_id = cur_btn_id; cmds->num_nav_cmds = button->num_nav_cmds; cmds->nav_cmds = button->nav_cmds; cmds->sound_id_ref = button->activated_sound_id_ref; break; default:; } } if (new_btn_id != cur_btn_id) { BD_IG_BUTTON *new_button = _find_button_page(page, new_btn_id, NULL); if (new_button) { cmds->sound_id_ref = new_button->selected_sound_id_ref; } } } } /* render page ? */ if (new_btn_id != cur_btn_id || activated_btn_id >= 0) { _select_button(gc, new_btn_id); _render_page(gc, activated_btn_id, cmds); /* found one*/ return 1; } return 0; }
int gc_run(GRAPHICS_CONTROLLER *gc, gc_ctrl_e ctrl, uint32_t param, GC_NAV_CMDS *cmds) { int result = -1; if (cmds) { cmds->num_nav_cmds = 0; cmds->nav_cmds = NULL; cmds->sound_id_ref = -1; cmds->status = GC_STATUS_NONE; } if (!gc) { GC_TRACE("gc_run(): no graphics controller\n"); return result; } bd_mutex_lock(&gc->mutex); /* always accept reset */ switch (ctrl) { case GC_CTRL_RESET: _gc_reset(gc); bd_mutex_unlock(&gc->mutex); return 0; default:; } /* other operations require complete display set */ if (!gc->igs || !gc->igs->ics || !gc->igs->complete) { GC_TRACE("gc_run(): no interactive composition\n"); bd_mutex_unlock(&gc->mutex); return result; } switch (ctrl) { case GC_CTRL_SET_BUTTON_PAGE: _set_button_page(gc, param); break; case GC_CTRL_VK_KEY: if (param != BD_VK_POPUP) { result = _user_input(gc, param, cmds); break; } param = !gc->popup_visible; /* fall thru (BD_VK_POPUP) */ case GC_CTRL_POPUP: if (gc->igs->ics->interactive_composition.ui_model != IG_UI_MODEL_POPUP) { /* not pop-up menu */ break; } gc->popup_visible = !!param; if (gc->popup_visible) { _select_page(gc, 0); } /* fall thru */ case GC_CTRL_NOP: result = _render_page(gc, 0xffff, cmds); break; case GC_CTRL_INIT_MENU: _select_page(gc, 0); _render_page(gc, 0xffff, cmds); break; case GC_CTRL_IG_END: _update_selected_button(gc); _render_page(gc, 0xffff, cmds); break; case GC_CTRL_ENABLE_BUTTON: _enable_button(gc, param, 1); break; case GC_CTRL_DISABLE_BUTTON: _enable_button(gc, param, 0); break; case GC_CTRL_MOUSE_MOVE: result = _mouse_move(gc, param >> 16, param & 0xffff, cmds); break; case GC_CTRL_RESET: /* already handled */ break; } if (cmds) { if (gc->igs->ics->interactive_composition.ui_model == IG_UI_MODEL_POPUP) { cmds->status |= GC_STATUS_POPUP; } if (gc->ig_drawn) { cmds->status |= GC_STATUS_MENU_OPEN; } } bd_mutex_unlock(&gc->mutex); return result; }
static void _set_button_page(GRAPHICS_CONTROLLER *gc, uint32_t param, GC_NAV_CMDS *cmds) { unsigned page_flag = param & 0x80000000; unsigned effect_flag = param & 0x40000000; unsigned button_flag = param & 0x20000000; unsigned page_id = (param >> 16) & 0xff; unsigned button_id = param & 0xffff; unsigned bog_idx = 0; PG_DISPLAY_SET *s = gc->igs; BD_IG_PAGE *page = NULL; BD_IG_BUTTON *button = NULL; TRACE("_set_button_page(0x%08x): page flag %d, id %d, effects %d button flag %d, id %d", param, !!page_flag, page_id, !!effect_flag, !!button_flag, button_id); /* 10.4.3.4 (D) */ if (!page_flag && !button_flag) { return; } if (page_flag) { /* current page --> command is ignored */ if (page_id == bd_psr_read(gc->regs, PSR_MENU_PAGE_ID)) { TRACE(" page is current\n"); return; } page = _find_page(&s->ics->interactive_composition, page_id); /* invalid page --> command is ignored */ if (!page) { TRACE(" page is invalid\n"); return; } /* page changes */ bd_psr_write(gc->regs, PSR_MENU_PAGE_ID, page_id); _reset_enabled_button(gc); _gc_clear_osd(gc, 1); } else { /* page does not change */ page_id = bd_psr_read(gc->regs, PSR_MENU_PAGE_ID); page = _find_page(&s->ics->interactive_composition, page_id); if (!page) { ERROR("_set_button_page(): PSR_MENU_PAGE_ID refers to unknown page %d\n", page_id); return; } } if (button_flag) { /* find correct button and overlap group */ button = _find_button_page(page, button_id, &bog_idx); if (!page_flag) { if (!button) { /* page not given, invalid button --> ignore command */ TRACE(" button is invalid\n"); return; } if (button_id == bd_psr_read(gc->regs, PSR_SELECTED_BUTTON_ID)) { /* page not given, current button --> ignore command */ TRACE(" button is current\n"); return; } } } if (!button) { button_id = 0xffff; // run 5.9.7.4 and 5.9.8.3 } else { gc->enabled_button[bog_idx] = button_id; } bd_psr_write(gc->regs, PSR_SELECTED_BUTTON_ID, button_id); gc->ig_drawn = 0; _render_page(gc, 0xffff, cmds); }