diff options
28 files changed, 156 insertions, 17 deletions
@@ -139,6 +139,12 @@ Device::BuiltinAction Device::InvokeMenuItem(int menu_position) { return entry->action.action; } +void Device::GoHome() { + while (menu_stack.size() > 1) { + menu_stack.pop(); + } +} + int Device::HandleMenuKey(int key, int visible) { if (!visible) { return kNoAction; @@ -164,8 +170,6 @@ int Device::HandleMenuKey(int key, int visible) { case KEY_ENTER: case KEY_POWER: case BTN_MOUSE: - case KEY_HOME: - case KEY_HOMEPAGE: case KEY_SEND: return kInvokeItem; @@ -173,6 +177,10 @@ int Device::HandleMenuKey(int key, int visible) { case KEY_BACK: return kGoBack; + case KEY_HOME: + case KEY_HOMEPAGE: + return kGoHome; + default: // If you have all of the above buttons, any other buttons // are ignored. Otherwise, any button cycles the highlight. @@ -92,12 +92,15 @@ class Device : public VoldWatcher { // actually perform it here and return NO_ACTION. virtual BuiltinAction InvokeMenuItem(int menu_position); + virtual void GoHome(); + static const int kNoAction = -1; static const int kHighlightUp = -2; static const int kHighlightDown = -3; static const int kInvokeItem = -4; static const int kGoBack = -5; - static const int kRefresh = -6; + static const int kGoHome = -6; + static const int kRefresh = -7; // Called before and after we do a wipe data/factory reset operation, // either via a reboot from the main system with the --wipe_data flag, diff --git a/recovery.cpp b/recovery.cpp index 35c6830..c13a689 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -662,7 +662,10 @@ get_menu_selection(const char* const * headers, const char* const * items, int selected = initial_selection; int chosen_item = -1; - while (chosen_item < 0 && chosen_item != Device::kGoBack && chosen_item != Device::kRefresh) { + while (chosen_item < 0 && + chosen_item != Device::kGoBack && + chosen_item != Device::kGoHome && + chosen_item != Device::kRefresh) { int key = ui->WaitKey(); int visible = ui->IsTextVisible(); @@ -713,6 +716,9 @@ get_menu_selection(const char* const * headers, const char* const * items, case Device::kGoBack: chosen_item = Device::kGoBack; break; + case Device::kGoHome: + chosen_item = Device::kGoHome; + break; case Device::kRefresh: chosen_item = Device::kRefresh; break; @@ -723,6 +729,9 @@ get_menu_selection(const char* const * headers, const char* const * items, } ui->EndMenu(); + if (chosen_item == Device::kGoHome) { + device->GoHome(); + } return chosen_item; } @@ -796,6 +805,11 @@ static char* browse_directory(const char* path, Device* device) { int chosen_item = 0; while (true) { chosen_item = get_menu_selection(headers, zips, 1, chosen_item, device); + if (chosen_item == Device::kGoHome) { + // go up and stop browsing + result = strdup(""); + break; + } if (chosen_item == 0 || chosen_item == Device::kGoBack) { // go up but continue browsing (if the caller is update_directory) result = NULL; @@ -936,6 +950,7 @@ static void choose_recovery_file(Device* device) { while (true) { int chosen_item = get_menu_selection(headers, entries, 1, 0, device); + if (chosen_item == Device::kGoHome) break; if (chosen_item == Device::kGoBack) break; if (chosen_item >= 0 && strcmp(entries[chosen_item], "Back") == 0) break; @@ -959,9 +974,10 @@ static int apply_from_storage(Device* device, const std::string& id, bool* wipe_ VolumeInfo vi = vdc->getVolume(id); char* path = browse_directory(vi.mInternalPath.c_str(), device); - if (path == NULL) { + if (path == NULL || *path == '\0') { ui->Print("\n-- No package file selected.\n"); vdc->volumeUnmount(vi.mId); + free(path); return INSTALL_NONE; } @@ -1013,6 +1029,9 @@ refresh: if (chosen == Device::kRefresh) { goto refresh; } + if (chosen == Device::kGoHome) { + return INSTALL_NONE; + } if (chosen == Device::kGoBack) { return INSTALL_NONE; } diff --git a/res-hdpi/images/icon_sysbar_back.png b/res-hdpi/images/icon_sysbar_back.png Binary files differnew file mode 100644 index 0000000..5aa8e62 --- /dev/null +++ b/res-hdpi/images/icon_sysbar_back.png diff --git a/res-hdpi/images/icon_sysbar_back_highlight.png b/res-hdpi/images/icon_sysbar_back_highlight.png Binary files differnew file mode 100644 index 0000000..5836504 --- /dev/null +++ b/res-hdpi/images/icon_sysbar_back_highlight.png diff --git a/res-hdpi/images/icon_sysbar_home.png b/res-hdpi/images/icon_sysbar_home.png Binary files differnew file mode 100644 index 0000000..b37422d --- /dev/null +++ b/res-hdpi/images/icon_sysbar_home.png diff --git a/res-hdpi/images/icon_sysbar_home_highlight.png b/res-hdpi/images/icon_sysbar_home_highlight.png Binary files differnew file mode 100644 index 0000000..ed0ccfa --- /dev/null +++ b/res-hdpi/images/icon_sysbar_home_highlight.png diff --git a/res-mdpi/images/icon_sysbar_back.png b/res-mdpi/images/icon_sysbar_back.png Binary files differnew file mode 100644 index 0000000..81e4637 --- /dev/null +++ b/res-mdpi/images/icon_sysbar_back.png diff --git a/res-mdpi/images/icon_sysbar_back_highlight.png b/res-mdpi/images/icon_sysbar_back_highlight.png Binary files differnew file mode 100644 index 0000000..d173042 --- /dev/null +++ b/res-mdpi/images/icon_sysbar_back_highlight.png diff --git a/res-mdpi/images/icon_sysbar_home.png b/res-mdpi/images/icon_sysbar_home.png Binary files differnew file mode 100644 index 0000000..d9e3a43 --- /dev/null +++ b/res-mdpi/images/icon_sysbar_home.png diff --git a/res-mdpi/images/icon_sysbar_home_highlight.png b/res-mdpi/images/icon_sysbar_home_highlight.png Binary files differnew file mode 100644 index 0000000..ef65d61 --- /dev/null +++ b/res-mdpi/images/icon_sysbar_home_highlight.png diff --git a/res-xhdpi/images/icon_sysbar_back.png b/res-xhdpi/images/icon_sysbar_back.png Binary files differnew file mode 100644 index 0000000..415715e --- /dev/null +++ b/res-xhdpi/images/icon_sysbar_back.png diff --git a/res-xhdpi/images/icon_sysbar_back_highlight.png b/res-xhdpi/images/icon_sysbar_back_highlight.png Binary files differnew file mode 100644 index 0000000..237af6a --- /dev/null +++ b/res-xhdpi/images/icon_sysbar_back_highlight.png diff --git a/res-xhdpi/images/icon_sysbar_home.png b/res-xhdpi/images/icon_sysbar_home.png Binary files differnew file mode 100644 index 0000000..425c0dc --- /dev/null +++ b/res-xhdpi/images/icon_sysbar_home.png diff --git a/res-xhdpi/images/icon_sysbar_home_highlight.png b/res-xhdpi/images/icon_sysbar_home_highlight.png Binary files differnew file mode 100644 index 0000000..f7b6ce3 --- /dev/null +++ b/res-xhdpi/images/icon_sysbar_home_highlight.png diff --git a/res-xxhdpi/images/icon_sysbar_back.png b/res-xxhdpi/images/icon_sysbar_back.png Binary files differnew file mode 100644 index 0000000..0b2e866 --- /dev/null +++ b/res-xxhdpi/images/icon_sysbar_back.png diff --git a/res-xxhdpi/images/icon_sysbar_back_highlight.png b/res-xxhdpi/images/icon_sysbar_back_highlight.png Binary files differnew file mode 100644 index 0000000..03cb8a1 --- /dev/null +++ b/res-xxhdpi/images/icon_sysbar_back_highlight.png diff --git a/res-xxhdpi/images/icon_sysbar_home.png b/res-xxhdpi/images/icon_sysbar_home.png Binary files differnew file mode 100644 index 0000000..7348841 --- /dev/null +++ b/res-xxhdpi/images/icon_sysbar_home.png diff --git a/res-xxhdpi/images/icon_sysbar_home_highlight.png b/res-xxhdpi/images/icon_sysbar_home_highlight.png Binary files differnew file mode 100644 index 0000000..a981495 --- /dev/null +++ b/res-xxhdpi/images/icon_sysbar_home_highlight.png diff --git a/res-xxxhdpi/images/icon_sysbar_back.png b/res-xxxhdpi/images/icon_sysbar_back.png Binary files differnew file mode 100644 index 0000000..f630553 --- /dev/null +++ b/res-xxxhdpi/images/icon_sysbar_back.png diff --git a/res-xxxhdpi/images/icon_sysbar_back_highlight.png b/res-xxxhdpi/images/icon_sysbar_back_highlight.png Binary files differnew file mode 100644 index 0000000..9211093 --- /dev/null +++ b/res-xxxhdpi/images/icon_sysbar_back_highlight.png diff --git a/res-xxxhdpi/images/icon_sysbar_home.png b/res-xxxhdpi/images/icon_sysbar_home.png Binary files differnew file mode 100644 index 0000000..9ee96ce --- /dev/null +++ b/res-xxxhdpi/images/icon_sysbar_home.png diff --git a/res-xxxhdpi/images/icon_sysbar_home_highlight.png b/res-xxxhdpi/images/icon_sysbar_home_highlight.png Binary files differnew file mode 100644 index 0000000..d63ecb0 --- /dev/null +++ b/res-xxxhdpi/images/icon_sysbar_home_highlight.png diff --git a/screen_ui.cpp b/screen_ui.cpp index 8e6c733..849f6d1 100644 --- a/screen_ui.cpp +++ b/screen_ui.cpp @@ -77,6 +77,7 @@ ScreenRecoveryUI::ScreenRecoveryUI() : show_menu(false), menu_items(0), menu_sel(0), + sysbar_state(0), file_viewer_text_(nullptr), animation_fps(20), installing_frames(-1), @@ -86,6 +87,10 @@ ScreenRecoveryUI::ScreenRecoveryUI() : wrap_count(0) { headerIcon = nullptr; + sysbarBackIcon = nullptr; + sysbarBackHighlightIcon = nullptr; + sysbarHomeIcon = nullptr; + sysbarHomeHighlightIcon = nullptr; for (int i = 0; i < NR_ICONS; i++) { backgroundIcon[i] = nullptr; } @@ -281,6 +286,45 @@ void ScreenRecoveryUI::draw_menu_item(int textrow, const char *text, int selecte } } +void ScreenRecoveryUI::draw_sysbar() +{ + GRSurface* surface; + int sw = gr_fb_width(); + int sh = gr_fb_height(); + int iw; + int ih; + SetColor(TEXT_FILL); + gr_fill(0, sh - sysbar_height_, sw, sh); + + // Left third is back button + if (!HasBackKey()) { + if (sysbar_state & SYSBAR_BACK) { + surface = sysbarBackHighlightIcon; + } + else { + surface = sysbarBackIcon; + } + iw = gr_get_width(surface); + ih = gr_get_height(surface); + gr_blit(surface, 0, 0, iw, ih, + 1 * (sw / 6) - (iw / 2), sh - ih); + } + + // Middle third is home button + if (!HasHomeKey()) { + if (sysbar_state & SYSBAR_HOME) { + surface = sysbarHomeHighlightIcon; + } + else { + surface = sysbarHomeIcon; + } + iw = gr_get_width(surface); + ih = gr_get_height(surface); + gr_blit(surface, 0, 0, iw, ih, + 3 * (sw / 6) - (iw / 2), sh - ih); + } +} + void ScreenRecoveryUI::draw_dialog() { int x, y, w, h; @@ -289,6 +333,7 @@ void ScreenRecoveryUI::draw_dialog() return; } draw_header_icon(); + draw_sysbar(); int iconHeight = gr_get_height(backgroundIcon[dialog_icon]); @@ -374,9 +419,9 @@ void ScreenRecoveryUI::draw_screen_locked() { } if (show_menu) { - int i; + int i, y; draw_header_icon(); - int y; + draw_sysbar(); // Divider y = text_first_row_ * char_height_; @@ -519,23 +564,31 @@ void ScreenRecoveryUI::Init() { gr_font_size(&log_char_width_, &log_char_height_); gr_set_font("menu"); gr_font_size(&char_width_, &char_height_); - text_rows_ = gr_fb_height() / char_height_; - text_cols_ = gr_fb_width() / char_width_; - - log_text_rows_ = gr_fb_height() / log_char_height_; - log_text_cols_ = gr_fb_width() / log_char_width_; - - text_ = Alloc2d(log_text_rows_, log_text_cols_ + 1); - file_viewer_text_ = Alloc2d(text_rows_, text_cols_ + 1); - menu_ = Alloc2d(text_rows_, text_cols_ + 1); text_col_ = text_row_ = 0; text_top_ = 1; LoadBitmap("icon_header", &headerIcon); + LoadBitmap("icon_sysbar_back", &sysbarBackIcon); + LoadBitmap("icon_sysbar_back_highlight", &sysbarBackHighlightIcon); + LoadBitmap("icon_sysbar_home", &sysbarHomeIcon); + LoadBitmap("icon_sysbar_home_highlight", &sysbarHomeHighlightIcon); + header_height_ = gr_get_height(headerIcon); header_width_ = gr_get_width(headerIcon); + sysbar_height_ = gr_get_height(sysbarBackIcon); + + text_rows_ = (gr_fb_height() - sysbar_height_) / char_height_; + text_cols_ = gr_fb_width() / char_width_; + + log_text_rows_ = (gr_fb_height() - sysbar_height_) / log_char_height_; + log_text_cols_ = gr_fb_width() / log_char_width_; + + text_ = Alloc2d(log_text_rows_, log_text_cols_ + 1); + file_viewer_text_ = Alloc2d(text_rows_, text_cols_ + 1); + menu_ = Alloc2d(text_rows_, text_cols_ + 1); + text_first_row_ = (header_height_ / char_height_) + 1; menu_item_start_ = text_first_row_ * char_height_; max_menu_rows_ = (text_rows_ - text_first_row_) / 3; diff --git a/screen_ui.h b/screen_ui.h index 93d06bc..9d7b263 100644 --- a/screen_ui.h +++ b/screen_ui.h @@ -23,6 +23,9 @@ #include "ui.h" #include "minui/minui.h" +#define SYSBAR_BACK 0x01 +#define SYSBAR_HOME 0x02 + // Implementation of RecoveryUI appropriate for devices with a screen // (shows an icon + a progress bar, text logging, menu, etc.) class ScreenRecoveryUI : public RecoveryUI { @@ -60,6 +63,11 @@ class ScreenRecoveryUI : public RecoveryUI { void DialogDismiss(); void SetHeadlessMode(); + // sysbar + int GetSysbarHeight() { return gr_get_height(sysbarBackHighlightIcon); } + int GetSysbarState() { return sysbar_state; } + void SetSysbarState(int state) { sysbar_state = state; Redraw(); } + // menu display virtual int MenuItemStart() const { return menu_item_start_; } virtual int MenuItemHeight() const { return 3 * char_height_; } @@ -87,6 +95,10 @@ class ScreenRecoveryUI : public RecoveryUI { pthread_cond_t progressCondition; GRSurface* headerIcon; + GRSurface* sysbarBackIcon; + GRSurface* sysbarBackHighlightIcon; + GRSurface* sysbarHomeIcon; + GRSurface* sysbarHomeHighlightIcon; GRSurface* backgroundIcon[NR_ICONS]; GRSurface* backgroundText[NR_ICONS]; GRSurface** installation; @@ -126,6 +138,8 @@ class ScreenRecoveryUI : public RecoveryUI { int menu_show_start_; int max_menu_rows_; + int sysbar_state; + // An alternate text screen, swapped with 'text_' when we're viewing a log file. char** file_viewer_text_; @@ -147,6 +161,7 @@ class ScreenRecoveryUI : public RecoveryUI { int char_height_, char_width_; int header_height_, header_width_; + int sysbar_height_; int text_first_row_; bool update_waiting; @@ -155,6 +170,7 @@ class ScreenRecoveryUI : public RecoveryUI { void draw_progress_locked(); int draw_header_icon(); void draw_menu_item(int textrow, const char *text, int selected); + void draw_sysbar(); void draw_dialog(); void draw_screen_locked(); void update_screen_locked(); @@ -144,7 +144,9 @@ RecoveryUI::RecoveryUI() last_key(-1), has_power_key(false), has_up_key(false), - has_down_key(false) { + has_down_key(false), + has_back_key(false), + has_home_key(false) { pthread_mutex_init(&key_queue_mutex, nullptr); pthread_cond_init(&key_queue_cond, nullptr); memset(key_pressed, 0, sizeof(key_pressed)); @@ -157,6 +159,12 @@ void RecoveryUI::OnKeyDetected(int key_code) { has_down_key = true; } else if (key_code == KEY_UP || key_code == KEY_VOLUMEUP) { has_up_key = true; + } else if (key_code == KEY_BACK) { + has_back_key = true; + LOGI("Detected back key, disabling virtual back button\n"); + } else if (key_code == KEY_HOMEPAGE) { + has_home_key = true; + LOGI("Detected home key, disabling virtual home button\n"); } } @@ -566,6 +574,12 @@ void RecoveryUI::handle_press(input_device* dev) { dev->touch_start = dev->touch_track = dev->touch_pos; dev->in_touch = true; dev->in_swipe = false; + if (dev->touch_pos.y >= gr_fb_height() - GetSysbarHeight()) { + SetSysbarState(1 << (3 * dev->touch_pos.x / gr_fb_width())); + } + else { + SetSysbarState(0); + } } void RecoveryUI::handle_release(input_device* dev) { @@ -588,6 +602,19 @@ void RecoveryUI::handle_release(input_device* dev) { return; } } + + int sysbar_state = GetSysbarState(); + SetSysbarState(0); + if (sysbar_state == 0x01) { + ProcessKey(dev, KEY_BACK, 1); + ProcessKey(dev, KEY_BACK, 0); + return; + } + if (sysbar_state == 0x02) { + ProcessKey(dev, KEY_HOME, 1); + ProcessKey(dev, KEY_HOME, 0); + return; + } } if (DialogShowing()) { @@ -162,6 +162,9 @@ class RecoveryUI { // of phones and tablets, false otherwise. virtual bool HasThreeButtons(); + virtual bool HasBackKey() const { return has_back_key; } + virtual bool HasHomeKey() const { return has_home_key; } + // Erase any queued-up keys. virtual void FlushKeys(); @@ -191,6 +194,10 @@ class RecoveryUI { virtual int MenuItemStart() const = 0; virtual int MenuItemHeight() const = 0; + virtual int GetSysbarHeight() = 0; + virtual int GetSysbarState() = 0; + virtual void SetSysbarState(int state) = 0; + // Display some header text followed by a menu of items, which appears // at the top of the screen (in place of any scrolling ui_print() // output, if necessary). @@ -230,6 +237,8 @@ private: bool has_power_key; bool has_up_key; bool has_down_key; + bool has_back_key; + bool has_home_key; input_device input_devices[MAX_NR_INPUT_DEVICES]; diff --git a/verifier_test.cpp b/verifier_test.cpp index 623ae64..a9d42c0 100644 --- a/verifier_test.cpp +++ b/verifier_test.cpp @@ -165,6 +165,10 @@ class FakeUI : public RecoveryUI { virtual int MenuItemStart() const { return 0; } virtual int MenuItemHeight() const { return 0; } + + virtual int GetSysbarHeight() { return 0; } + virtual int GetSysbarState() { return 0; } + virtual void SetSysbarState(int state) {} }; void |