aboutsummaryrefslogtreecommitdiffstats
path: root/screen_ui.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'screen_ui.cpp')
-rw-r--r--screen_ui.cpp496
1 files changed, 424 insertions, 72 deletions
diff --git a/screen_ui.cpp b/screen_ui.cpp
index 2f8b07b9..41d0594a 100644
--- a/screen_ui.cpp
+++ b/screen_ui.cpp
@@ -37,6 +37,8 @@
#include <android-base/strings.h>
#include <android-base/stringprintf.h>
+#include <healthd/BatteryMonitor.h>
+
#include "common.h"
#include "device.h"
#include "minui/minui.h"
@@ -50,6 +52,69 @@ static double now() {
return tv.tv_sec + tv.tv_usec / 1000000.0;
}
+static void get_battery_status(bool& charged, int& capacity) {
+ struct healthd_config healthd_config = {
+ .batteryStatusPath = android::String8(android::String8::kEmptyString),
+ .batteryHealthPath = android::String8(android::String8::kEmptyString),
+ .batteryPresentPath = android::String8(android::String8::kEmptyString),
+ .batteryCapacityPath = android::String8(android::String8::kEmptyString),
+ .batteryVoltagePath = android::String8(android::String8::kEmptyString),
+ .batteryTemperaturePath = android::String8(android::String8::kEmptyString),
+ .batteryTechnologyPath = android::String8(android::String8::kEmptyString),
+ .batteryCurrentNowPath = android::String8(android::String8::kEmptyString),
+ .batteryCurrentAvgPath = android::String8(android::String8::kEmptyString),
+ .batteryChargeCounterPath = android::String8(android::String8::kEmptyString),
+ .batteryFullChargePath = android::String8(android::String8::kEmptyString),
+ .batteryCycleCountPath = android::String8(android::String8::kEmptyString),
+ .energyCounter = NULL,
+ .boot_min_cap = 0,
+ .screen_on = NULL
+ };
+ healthd_board_init(&healthd_config);
+
+ android::BatteryMonitor monitor;
+ monitor.init(&healthd_config);
+
+ int charge_status = monitor.getChargeStatus();
+ // Treat unknown status as charged.
+ charged = (charge_status != android::BATTERY_STATUS_DISCHARGING &&
+ charge_status != android::BATTERY_STATUS_NOT_CHARGING);
+ android::BatteryProperty prop;
+ android::status_t status = monitor.getProperty(android::BATTERY_PROP_CAPACITY, &prop);
+ // If we can't read battery percentage, it may be a device without battery. In this
+ // situation, use 100 as a fake battery percentage.
+ if (status != 0) {
+ prop.valueInt64 = 100;
+ }
+ capacity = (int)prop.valueInt64;
+}
+
+ScreenMenuItem::~ScreenMenuItem() {
+ if (icon_) {
+ res_free_surface(icon_);
+ }
+ if (icon_sel_) {
+ res_free_surface(icon_sel_);
+ }
+}
+
+GRSurface* ScreenMenuItem::icon() {
+ if (!icon_) {
+ res_create_display_surface(icon_name_.c_str(), &icon_);
+ }
+ return icon_;
+}
+
+GRSurface* ScreenMenuItem::icon_sel() {
+ if (icon_name_sel_.empty()) {
+ return icon();
+ }
+ if (!icon_sel_) {
+ res_create_display_surface(icon_name_sel_.c_str(), &icon_sel_);
+ }
+ return icon_sel_;
+}
+
ScreenRecoveryUI::ScreenRecoveryUI()
: kMarginWidth(RECOVERY_UI_MARGIN_WIDTH),
kMarginHeight(RECOVERY_UI_MARGIN_HEIGHT),
@@ -69,9 +134,13 @@ ScreenRecoveryUI::ScreenRecoveryUI()
text_top_(0),
show_text(false),
show_text_ever(false),
- menu_(nullptr),
+ menu_is_main_(true),
+ menu_type_(MT_NONE),
+ menu_headers_(nullptr),
+ menu_start_y_(0),
show_menu(false),
- menu_items(0),
+ menu_show_start(0),
+ menu_show_count(0),
menu_sel(0),
file_viewer_text_(nullptr),
intro_frames(0),
@@ -180,7 +249,7 @@ void ScreenRecoveryUI::draw_background_locked() {
// Draws the animation and progress bar (if any) on the screen. Does not flip pages. Should only be
// called with updateMutex locked.
void ScreenRecoveryUI::draw_foreground_locked() {
- if (currentIcon != NONE) {
+ if (currentIcon != NONE && currentIcon != NO_COMMAND) {
gr_color(0, 0, 0, 255);
gr_clear();
GRSurface* frame = GetCurrentFrame();
@@ -228,8 +297,12 @@ void ScreenRecoveryUI::draw_foreground_locked() {
}
}
+/* Lineage teal: #167c80 */
void ScreenRecoveryUI::SetColor(UIElement e) const {
switch (e) {
+ case STATUSBAR:
+ gr_color(255, 255, 255, 255);
+ break;
case INFO:
gr_color(249, 194, 0, 255);
break;
@@ -238,13 +311,13 @@ void ScreenRecoveryUI::SetColor(UIElement e) const {
break;
case MENU:
case MENU_SEL_BG:
- gr_color(106, 103, 102, 255);
+ gr_color(0xd8, 0xd8, 0xd8, 255);
break;
case MENU_SEL_BG_ACTIVE:
gr_color(138, 135, 134, 255);
break;
case MENU_SEL_FG:
- gr_color(0, 177, 229, 255);
+ gr_color(0x16, 0x7c, 0x80, 255);
break;
case LOG:
gr_color(196, 196, 196, 255);
@@ -302,7 +375,8 @@ int ScreenRecoveryUI::DrawWrappedTextLines(int x, int y, const char* const* line
next_start += last_space + 1;
}
}
- offset += DrawTextLine(x, y + offset, sub.c_str(), false);
+ gr_text(gr_menu_font(), x, y + offset, sub.c_str(), false);
+ offset += menu_char_height_ + 4;
}
}
return offset;
@@ -319,6 +393,215 @@ static const char* LONG_PRESS_HELP[] = {
NULL
};
+void ScreenRecoveryUI::draw_statusbar_locked() {
+ int y = kMarginHeight;
+ int x;
+
+ int h_unit = gr_fb_width() / 9;
+ int v_unit = gr_fb_height() / 16;
+
+ GRSurface* icon;
+ int icon_x, icon_y, icon_h, icon_w;
+
+ // Local time
+ char localtm_str[] = "--:--";
+ time_t now;
+ struct tm localtm;
+ time(&now);
+ if (now > TV_MIN) {
+ localtime_r(&now, &localtm);
+ snprintf(localtm_str, sizeof(localtm_str), "%02d:%02d",
+ localtm.tm_hour, localtm.tm_min);
+ }
+
+ // Battery status
+ bool batt_charged;
+ int batt_capacity;
+ get_battery_status(batt_charged, batt_capacity);
+ char batt_capacity_str[3+1+1];
+ snprintf(batt_capacity_str, sizeof(batt_capacity_str), "%d%%", batt_capacity);
+
+ // Draw status bar from right to left
+
+ // Time
+ SetColor(STATUSBAR);
+ x = gr_fb_width();
+ x -= 5 * char_width_;
+ gr_text(gr_sys_font(), x, y, localtm_str, false);
+
+ x -= char_width_; // Separator
+
+ // Battery icon
+ x -= 1 * char_width_;
+ SetColor((batt_capacity < 20) ? HEADER : STATUSBAR);
+
+ // Top
+ icon_x = x + char_width_ / 3;
+ icon_y = y;
+ icon_w = char_width_ / 3;
+ icon_h = char_height_ / 12;
+ gr_fill(icon_x, icon_y, icon_x + icon_w, icon_y + icon_h);
+
+ // Main rect
+ icon_x = x;
+ icon_y = y + icon_h;
+ icon_w = char_width_;
+ icon_h = char_height_ - (char_height_ / 12);
+ gr_fill(icon_x, icon_y, icon_x + icon_w, icon_y + icon_h);
+
+ // Capacity
+ icon_x = x + char_width_ / 6;
+ icon_y = y + char_height_ / 12;
+ icon_w = char_width_ - (2 * char_width_ / 6);
+ icon_h = char_height_ - (3 * char_height_ / 12);
+ int cap_h = icon_h * batt_capacity / 100;
+ gr_fill(icon_x, icon_y + icon_h - cap_h, icon_x + icon_w, icon_y + icon_h);
+ gr_color(0, 0, 0, 255);
+ gr_fill(icon_x, icon_y, icon_x + icon_w, icon_y + icon_h - cap_h);
+ SetColor(STATUSBAR);
+
+ x -= char_width_; // Separator
+
+ // Battery text
+ x -= strlen(batt_capacity_str) * char_width_;
+ gr_text(gr_sys_font(), x, y, batt_capacity_str, false);
+}
+
+/*
+ * Header layout:
+ * * 1/32: Status bar
+ * * Header image
+ * * 1/32: Margin
+ */
+void ScreenRecoveryUI::draw_header_locked(int& y) {
+ int h_unit = gr_fb_width() / 9;
+ int v_unit = gr_fb_height() / 16;
+
+ GRSurface* icon;
+ int icon_x, icon_y, icon_h, icon_w;
+
+ y += v_unit / 2; // Margin
+
+ // Draw back icon if not in main menu
+ if (!menu_is_main_) {
+ icon = (menu_sel == Device::kGoBack ? ic_back_sel : ic_back);
+ icon_w = gr_get_width(icon);
+ icon_h = gr_get_height(icon);
+ icon_x = (h_unit / 2) + ((h_unit * 1) - icon_w) / 2;
+ icon_y = y + ((v_unit * 1) - icon_h) / 2;
+ gr_blit(icon, 0, 0, icon_w, icon_h, icon_x, icon_y);
+ }
+ y += v_unit;
+
+ // Draw logo
+ icon = logo_image;
+ icon_w = gr_get_width(icon);
+ icon_h = gr_get_height(icon);
+ icon_x = (gr_fb_width() - icon_w) / 2;
+ icon_y = y + ((v_unit * 4) - icon_h) / 2;
+ gr_blit(icon, 0, 0, icon_w, icon_h, icon_x, icon_y);
+ y += v_unit * 4;
+
+ y += v_unit * 1; // Margin
+}
+
+void ScreenRecoveryUI::draw_text_menu_locked(int& y) {
+ static constexpr int kMenuIndent = 4;
+ int x = kMarginWidth + kMenuIndent;
+
+ draw_statusbar_locked();
+ draw_header_locked(y);
+
+ if (menu_headers_) {
+ SetColor(HEADER);
+ // Ignore kMenuIndent, which is not taken into account by text_cols_.
+ y += DrawWrappedTextLines(kMarginWidth, y, menu_headers_);
+
+ SetColor(MENU);
+ y += DrawHorizontalRule(y) + 4;
+ }
+
+ menu_start_y_ = y;
+ int i;
+ for (i = menu_show_start; i < (int)menu_items_.size() && y < gr_fb_height(); ++i) {
+ const ScreenMenuItem& item = menu_items_.at(i);
+ if (i == menu_sel) {
+ SetColor(MENU_SEL_FG);
+ y += menu_char_height_;
+ gr_text(gr_menu_font(), x, y, item.text().c_str(), true);
+ y += menu_char_height_;
+ y += menu_char_height_;
+ } else {
+ SetColor(MENU);
+ y += menu_char_height_;
+ gr_text(gr_menu_font(), x, y, item.text().c_str(), false);
+ y += menu_char_height_;
+ y += menu_char_height_;
+ }
+ }
+ menu_show_count = i - menu_show_start;
+}
+
+/*
+ * Grid layout.
+ *
+ * Grid item:
+ * Horizontal:
+ * * 3/9 of screen per item.
+ * * 1/9 of screen margin around/between items.
+ * Vertical:
+ * * 3/16 of screen per item.
+ * * No margin between items.
+ *
+ * Within a grid item:
+ * Asher's icons 1/5 of grid both dimensions.
+ * Current icons 2/5 of grid both dimensions.
+ * Horizontal:
+ * * All items centered.
+ * Vertical:
+ * * Icon lower aligned in top 2/3.
+ * * Text upper aligned in low 1/3 plus half line margin.
+ */
+void ScreenRecoveryUI::draw_grid_menu_locked(int& y) {
+ int h_unit = gr_fb_width() / 9;
+ int v_unit = gr_fb_height() / 16;
+
+ int grid_w = h_unit * 3;
+ int grid_h = v_unit * 3;
+
+ draw_statusbar_locked();
+ draw_header_locked(y);
+
+ menu_start_y_ = y;
+ int i;
+ for (i = menu_show_start; i < (int)menu_items_.size() && y + grid_h < gr_fb_height(); ++i) {
+ ScreenMenuItem& item = menu_items_.at(i);
+ int grid_x = (i % 2) ? h_unit * 5 : h_unit * 1;
+ int grid_y = y;
+ if (item.icon()) {
+ GRSurface* icon = (i == menu_sel) ? item.icon_sel() : item.icon();
+ int icon_w = gr_get_width(icon);
+ int icon_h = gr_get_height(icon);
+ int icon_x = grid_x + (grid_w - icon_w) / 2;
+ int icon_y = grid_y + ((grid_h * 2 / 3) - icon_h) / 2;
+ gr_blit(icon, 0, 0, icon_w, icon_h, icon_x, icon_y);
+ }
+ if (!item.text().empty()) {
+ int text_w = item.text().size() * char_width_;
+ int text_h = char_height_;
+ int text_x = grid_x + (grid_w - text_w) / 2;
+ int text_y = grid_y + (grid_h * 2 / 3) + (char_height_ / 2);
+ SetColor(i == menu_sel ? MENU_SEL_FG : MENU);
+ gr_text(gr_sys_font(), text_x, text_y, item.text().c_str(), false);
+ }
+ if (i % 2) {
+ y += grid_h;
+ grid_y = y;
+ }
+ }
+ menu_show_count = i - menu_show_start;
+}
+
// Redraws everything on the screen. Does not flip pages. Should only be called with updateMutex
// locked.
void ScreenRecoveryUI::draw_screen_locked() {
@@ -333,50 +616,40 @@ void ScreenRecoveryUI::draw_screen_locked() {
int y = kMarginHeight;
if (show_menu) {
- static constexpr int kMenuIndent = 4;
- int x = kMarginWidth + kMenuIndent;
-
- SetColor(INFO);
- y += DrawTextLine(x, y, "Android Recovery", true);
- std::string recovery_fingerprint =
- android::base::GetProperty("ro.bootimage.build.fingerprint", "");
- for (const auto& chunk : android::base::Split(recovery_fingerprint, ":")) {
- y += DrawTextLine(x, y, chunk.c_str(), false);
+ switch (menu_type_) {
+ case MT_LIST:
+ draw_text_menu_locked(y);
+ break;
+ case MT_GRID:
+ draw_grid_menu_locked(y);
+ break;
+ default:
+ break;
}
- y += DrawTextLines(x, y, HasThreeButtons() ? REGULAR_HELP : LONG_PRESS_HELP);
-
- SetColor(HEADER);
- // Ignore kMenuIndent, which is not taken into account by text_cols_.
- y += DrawWrappedTextLines(kMarginWidth, y, menu_headers_);
- SetColor(MENU);
- y += DrawHorizontalRule(y) + 4;
- for (int i = 0; i < menu_items; ++i) {
- if (i == menu_sel) {
- // Draw the highlight bar.
- SetColor(IsLongPress() ? MENU_SEL_BG_ACTIVE : MENU_SEL_BG);
- DrawHighlightBar(0, y - 2, gr_fb_width(), char_height_ + 4);
- // Bold white text for the selected item.
- SetColor(MENU_SEL_FG);
- y += DrawTextLine(x, y, menu_[i], true);
- SetColor(MENU);
- } else {
- y += DrawTextLine(x, y, menu_[i], false);
- }
+ // Draw version info
+ if (menu_is_main_) {
+ int text_x, text_y;
+ text_x = (gr_fb_width() - (android_version_.size() * char_width_)) / 2;
+ text_y = gr_fb_height() - 2 * (char_height_ + 4);
+ DrawTextLine(text_x, text_y, android_version_.c_str(), false);
+ text_x = (gr_fb_width() - (lineage_version_.size() * char_width_)) / 2;
+ text_y = gr_fb_height() - 1 * (char_height_ + 4);
+ DrawTextLine(text_x, text_y, lineage_version_.c_str(), false);
}
- y += DrawHorizontalRule(y);
}
-
- // Display from the bottom up, until we hit the top of the screen, the bottom of the menu, or
- // we've displayed the entire text buffer.
- SetColor(LOG);
- int row = (text_top_ + text_rows_ - 1) % text_rows_;
- size_t count = 0;
- for (int ty = gr_fb_height() - kMarginHeight - char_height_; ty >= y && count < text_rows_;
- ty -= char_height_, ++count) {
- DrawTextLine(kMarginWidth, ty, text_[row], false);
- --row;
- if (row < 0) row = text_rows_ - 1;
+ else {
+ // Display from the bottom up, until we hit the top of the screen, the bottom of the menu, or
+ // we've displayed the entire text buffer.
+ SetColor(LOG);
+ int row = (text_top_ + text_rows_ - 1) % text_rows_;
+ size_t count = 0;
+ for (int ty = gr_fb_height() - kMarginHeight - char_height_; ty >= y && count < text_rows_;
+ ty -= char_height_, ++count) {
+ DrawTextLine(kMarginWidth, ty, text_[row], false);
+ --row;
+ if (row < 0) row = text_rows_ - 1;
+ }
}
}
@@ -459,6 +732,10 @@ void ScreenRecoveryUI::LoadBitmap(const char* filename, GRSurface** surface) {
}
}
+void ScreenRecoveryUI::FreeBitmap(GRSurface* surface) {
+ res_free_surface(surface);
+}
+
void ScreenRecoveryUI::LoadLocalizedBitmap(const char* filename, GRSurface** surface) {
int result = res_create_localized_alpha_surface(filename, locale_.c_str(), surface);
if (result < 0) {
@@ -491,6 +768,7 @@ bool ScreenRecoveryUI::InitTextParams() {
}
gr_font_size(gr_sys_font(), &char_width_, &char_height_);
+ gr_font_size(gr_menu_font(), &menu_char_width_, &menu_char_height_);
text_rows_ = (gr_fb_height() - kMarginHeight * 2) / char_height_;
text_cols_ = (gr_fb_width() - kMarginWidth * 2) / char_width_;
return true;
@@ -509,11 +787,14 @@ bool ScreenRecoveryUI::Init(const std::string& locale) {
text_ = Alloc2d(text_rows_, 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("logo_image", &logo_image);
+ LoadBitmap("ic_back", &ic_back);
+ LoadBitmap("ic_back_sel", &ic_back_sel);
+
LoadBitmap("icon_error", &error_icon);
LoadBitmap("progress_empty", &progressBarEmpty);
@@ -580,8 +861,10 @@ void ScreenRecoveryUI::LoadAnimation() {
void ScreenRecoveryUI::SetBackground(Icon icon) {
pthread_mutex_lock(&updateMutex);
- currentIcon = icon;
- update_screen_locked();
+ if (icon != currentIcon) {
+ currentIcon = icon;
+ update_screen_locked();
+ }
pthread_mutex_unlock(&updateMutex);
}
@@ -698,7 +981,7 @@ void ScreenRecoveryUI::ClearText() {
pthread_mutex_unlock(&updateMutex);
}
-void ScreenRecoveryUI::ShowFile(FILE* fp) {
+int ScreenRecoveryUI::ShowFile(FILE* fp) {
std::vector<off_t> offsets;
offsets.push_back(ftello(fp));
ClearText();
@@ -715,10 +998,16 @@ void ScreenRecoveryUI::ShowFile(FILE* fp) {
Redraw();
while (show_prompt) {
show_prompt = false;
- int key = WaitKey();
- if (key == KEY_POWER || key == KEY_ENTER) {
- return;
- } else if (key == KEY_UP || key == KEY_VOLUMEUP) {
+ RecoveryUI::InputEvent evt = WaitInputEvent();
+ if (evt.type() != RecoveryUI::EVENT_TYPE_KEY) {
+ show_prompt = true;
+ continue;
+ }
+ if (evt.key() == KEY_POWER || evt.key() == KEY_ENTER ||
+ evt.key() == KEY_BACKSPACE || evt.key() == KEY_BACK ||
+ evt.key() == KEY_HOME || evt.key() == KEY_HOMEPAGE) {
+ return evt.key();
+ } else if (evt.key() == KEY_UP || evt.key() == KEY_VOLUMEUP) {
if (offsets.size() <= 1) {
show_prompt = true;
} else {
@@ -727,7 +1016,7 @@ void ScreenRecoveryUI::ShowFile(FILE* fp) {
}
} else {
if (feof(fp)) {
- return;
+ return -1;
}
offsets.push_back(ftello(fp));
}
@@ -746,13 +1035,14 @@ void ScreenRecoveryUI::ShowFile(FILE* fp) {
}
}
}
+ return -1;
}
-void ScreenRecoveryUI::ShowFile(const char* filename) {
+int ScreenRecoveryUI::ShowFile(const char* filename) {
FILE* fp = fopen_path(filename, "re");
if (fp == nullptr) {
Print(" Unable to open %s: %s\n", filename, strerror(errno));
- return;
+ return -1;
}
char** old_text = text_;
@@ -764,30 +1054,38 @@ void ScreenRecoveryUI::ShowFile(const char* filename) {
text_ = file_viewer_text_;
ClearText();
- ShowFile(fp);
+ int key = ShowFile(fp);
fclose(fp);
text_ = old_text;
text_col_ = old_text_col;
text_row_ = old_text_row;
text_top_ = old_text_top;
+ return key;
}
-void ScreenRecoveryUI::StartMenu(const char* const* headers, const char* const* items,
+void ScreenRecoveryUI::StartMenu(bool is_main,
+ menu_type_t type,
+ const char* const* headers,
+ const MenuItemVector& items,
int initial_selection) {
pthread_mutex_lock(&updateMutex);
- if (text_rows_ > 0 && text_cols_ > 0) {
- menu_headers_ = headers;
- size_t i = 0;
- for (; i < text_rows_ && items[i] != nullptr; ++i) {
- strncpy(menu_[i], items[i], text_cols_ - 1);
- menu_[i][text_cols_ - 1] = '\0';
- }
- menu_items = i;
- show_menu = true;
- menu_sel = initial_selection;
- update_screen_locked();
+ menu_is_main_ = is_main;
+ menu_type_ = type;
+ menu_headers_ = headers;
+ for (auto& item : items) {
+ menu_items_.push_back(ScreenMenuItem(item));
+ }
+ show_menu = true;
+ menu_sel = initial_selection;
+ draw_screen_locked();
+ if (menu_sel < menu_show_start) {
+ menu_show_start = menu_sel;
+ }
+ if (menu_sel >= menu_show_start + menu_show_count) {
+ menu_show_start = menu_sel - (menu_show_count - 1);
}
+ update_screen_locked();
pthread_mutex_unlock(&updateMutex);
}
@@ -798,8 +1096,16 @@ int ScreenRecoveryUI::SelectMenu(int sel) {
menu_sel = sel;
// Wrap at top and bottom.
- if (menu_sel < 0) menu_sel = menu_items - 1;
- if (menu_sel >= menu_items) menu_sel = 0;
+ if (menu_sel < 0) menu_sel = (int)menu_items_.size() - 1;
+ if (menu_sel >= (int)menu_items_.size()) menu_sel = 0;
+
+ // Scroll
+ if (menu_sel < menu_show_start) {
+ menu_show_start = menu_sel;
+ }
+ if (menu_sel >= menu_show_start + menu_show_count) {
+ menu_show_start = menu_sel - (menu_show_count - 1);
+ }
sel = menu_sel;
if (menu_sel != old_sel) update_screen_locked();
@@ -808,11 +1114,57 @@ int ScreenRecoveryUI::SelectMenu(int sel) {
return sel;
}
+int ScreenRecoveryUI::SelectMenu(const Point& point) {
+ int sel = Device::kNoAction;
+ int h_unit = gr_fb_width() / 9;
+ int v_unit = gr_fb_height() / 16;
+ pthread_mutex_lock(&updateMutex);
+ if (show_menu) {
+ if (point.y() < menu_start_y_) {
+ if (!menu_is_main_ &&
+ point.x() >= h_unit / 2 && point.x() < h_unit * 3 / 2 &&
+ point.y() >= v_unit * 1 / 2 && point.y() < v_unit * 3 / 2) {
+ sel = Device::kGoBack;
+ }
+ }
+ else {
+ int row = -1, col = -1;
+ switch (menu_type_) {
+ case MT_LIST:
+ sel = (point.y() - menu_start_y_) / (menu_char_height_ * 3);
+ break;
+ case MT_GRID:
+ row = (point.y() - menu_start_y_) / (gr_fb_height() * 3 / 16);
+ col = (point.x()) / (gr_fb_width() / 9);
+ if ((col % 4) != 0) {
+ sel = row * 2 + ((col - 1) / 4);
+ }
+ break;
+ default:
+ break;
+ }
+ if (sel >= (int)menu_items_.size()) {
+ sel = Device::kNoAction;
+ }
+ }
+ if (sel != -1 && sel != menu_sel) {
+ menu_sel = sel;
+ update_screen_locked();
+ usleep(100*1000);
+ }
+ }
+ pthread_mutex_unlock(&updateMutex);
+ return sel;
+}
+
void ScreenRecoveryUI::EndMenu() {
pthread_mutex_lock(&updateMutex);
if (show_menu && text_rows_ > 0 && text_cols_ > 0) {
show_menu = false;
}
+ menu_type_ = MT_NONE;
+ menu_headers_ = nullptr;
+ menu_items_.clear();
pthread_mutex_unlock(&updateMutex);
}