| 362 | } |
| 363 | |
| 364 | void KeyboardEntryActivity::render(RenderLock&&) { |
| 365 | renderer.clearScreen(); |
| 366 | |
| 367 | const auto pageWidth = renderer.getScreenWidth(); |
| 368 | const auto pageHeight = renderer.getScreenHeight(); |
| 369 | const auto& metrics = UITheme::getInstance().getMetrics(); |
| 370 | |
| 371 | GUI.drawHeader(renderer, Rect{0, metrics.topPadding, pageWidth, metrics.headerHeight}, title.c_str()); |
| 372 | |
| 373 | const int lineHeight = renderer.getLineHeight(UI_12_FONT_ID); |
| 374 | const int inputStartY = metrics.topPadding + metrics.headerHeight + metrics.verticalSpacing + |
| 375 | metrics.verticalSpacing * 4 + metrics.keyboardVerticalOffset; |
| 376 | int inputHeight = 0; |
| 377 | |
| 378 | std::string displayText; |
| 379 | if (inputType == InputType::Password && !passwordVisible) { |
| 380 | size_t revealPos; |
| 381 | if (cursorMode) { |
| 382 | revealPos = text.length(); // no reveal in displayText; block draws actual char directly |
| 383 | } else { |
| 384 | revealPos = (text.length() > 0 && cursorPos > 0) ? cursorPos - 1 : std::string::npos; |
| 385 | } |
| 386 | displayText = text; |
| 387 | for (size_t i = 0; i < displayText.length(); i++) { |
| 388 | if (i != revealPos) { |
| 389 | displayText[i] = '*'; |
| 390 | } |
| 391 | } |
| 392 | } else { |
| 393 | displayText = text; |
| 394 | } |
| 395 | |
| 396 | const bool isPassword = (inputType == InputType::Password); |
| 397 | int availableWidth = pageWidth; |
| 398 | if (gpio.deviceIsX3()) { |
| 399 | availableWidth -= 2 * metrics.sideButtonHintsWidth; |
| 400 | } |
| 401 | const int effectiveMargin = (pageWidth - availableWidth * metrics.keyboardTextFieldWidthPercent / 100) / 2; |
| 402 | const int toggleGap = isPassword ? 4 : 0; |
| 403 | const int toggleReserve = isPassword ? std::max(renderer.getTextWidth(UI_12_FONT_ID, "[abc]"), |
| 404 | renderer.getTextWidth(UI_12_FONT_ID, "[***]")) + |
| 405 | toggleGap |
| 406 | : 0; |
| 407 | const int textAreaWidth = pageWidth - 2 * effectiveMargin - toggleReserve; |
| 408 | const int maxLineWidth = textAreaWidth; |
| 409 | const bool centerText = metrics.keyboardCenteredText; |
| 410 | |
| 411 | int cursorCharWidth = 6; |
| 412 | if (cursorPos < text.length()) { |
| 413 | int w = renderer.getTextWidth(UI_12_FONT_ID, text.substr(cursorPos, 1).c_str()); |
| 414 | if (w > cursorCharWidth) cursorCharWidth = w; |
| 415 | } |
| 416 | |
| 417 | int lineStartIdx = 0; |
| 418 | int lineEndIdx = displayText.length(); |
| 419 | int textWidth = 0; |
| 420 | int cursorPixelX = effectiveMargin; |
| 421 | int cursorLineY = inputStartY; |
nothing calls this directly
no test coverage detected