mirror of
https://github.com/InstanceBrick/nightcap.git
synced 2026-10-23 12:01:04 +02:00
Fix chat text render and chat shiftlock issues
Fixes 106, Fixes #127, Refs #116
This commit is contained in:
1 parent
c523048518
commit
0548ebd253
13 files changed
+206
-16
No files matched your search
@@ -526,7 +526,10 @@ RobloxInputDispatchResult RobloxInputRouter::HandleEvent(
|
||||
|
||||
RobloxInputSnapshot RobloxInputRouter::Snapshot() const {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
return snapshot_;
|
||||
RobloxInputSnapshot snapshot = snapshot_;
|
||||
const RobloxTextEditorSnapshot text = text_editor_.Snapshot();
|
||||
snapshot.text_focus_generation = text.focused ? text.generation : 0;
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
RobloxInputDispatchResult RobloxInputRouter::HandleMouseMotionLocked(
|
||||
|
||||
@@ -14,8 +14,6 @@ namespace mocktail {
|
||||
namespace runtime {
|
||||
namespace {
|
||||
|
||||
constexpr int kMinimumNativeWidth = 32;
|
||||
constexpr int kMinimumNativeHeight = 18;
|
||||
constexpr char kPasswordBullet[] = "\xE2\x80\xA2";
|
||||
|
||||
void SecureClear(std::string* value) {
|
||||
@@ -83,8 +81,8 @@ bool ValidateAndCountUtf8(const char* text, std::size_t size,
|
||||
bool NativeGeometryIntersectsViewport(
|
||||
const RobloxTextDisplayUpdate& update,
|
||||
const RobloxTextOverlayViewport& viewport) {
|
||||
if (!viewport.valid() || update.area_width < kMinimumNativeWidth ||
|
||||
update.area_height < kMinimumNativeHeight) {
|
||||
if (!viewport.valid() || update.area_width <= 0 ||
|
||||
update.area_height <= 0) {
|
||||
return false;
|
||||
}
|
||||
const int64_t right = static_cast<int64_t>(update.area_x) +
|
||||
|
||||
@@ -142,6 +142,9 @@ class ProductionTextInputBackend final
|
||||
return runtime_->EndTextFocusSession(textbox_handle, generation,
|
||||
notify_native);
|
||||
}
|
||||
bool IsTextFocusSessionActive(uint64_t generation) override {
|
||||
return runtime_->Snapshot().text_focus_generation == generation;
|
||||
}
|
||||
Status ReplaceFocusedTextFromEngine(uint64_t generation,
|
||||
std::string authoritative_utf8) override {
|
||||
return runtime_->ReplaceFocusedTextFromEngine(
|
||||
@@ -559,6 +562,44 @@ struct RobloxTextInputJniBridge::State {
|
||||
return CompleteTerminalOnMainThread("queue");
|
||||
}
|
||||
|
||||
// RbxKeyboard hides its own editor after Enter/Escape. The native side
|
||||
// need not echo hideKeyboard, so reconcile the host editor before polling
|
||||
// properties or replaying delayed text updates from that focus session.
|
||||
if (applied_active &&
|
||||
!backend->IsTextFocusSessionActive(applied_generation)) {
|
||||
const uint64_t ended_generation = applied_generation;
|
||||
if (!backend->RequestHideTextInput(ended_generation)) {
|
||||
for (Command& command : pending) command.ClearSensitiveData();
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
EnterTerminalLocked("SDL text-input completion hide was rejected");
|
||||
}
|
||||
return CompleteTerminalOnMainThread("host-focus-end");
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
if (active_generation == ended_generation) {
|
||||
desired_active = false;
|
||||
active_handle = 0;
|
||||
active_info = {};
|
||||
active_geometry = {};
|
||||
has_active_geometry = false;
|
||||
geometry_refresh_pumps = 0;
|
||||
}
|
||||
}
|
||||
for (auto it = pending.begin(); it != pending.end();) {
|
||||
if (it->generation == ended_generation) {
|
||||
it->ClearSensitiveData();
|
||||
it = pending.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
applied_active = false;
|
||||
applied_generation = 0;
|
||||
applied_handle = 0;
|
||||
}
|
||||
|
||||
AppendGeometryRefresh(&pending);
|
||||
|
||||
bool success = true;
|
||||
|
||||
@@ -27,6 +27,7 @@ class RobloxTextInputJniBridgeBackend {
|
||||
virtual Status EndTextFocusSession(int64_t textbox_handle,
|
||||
uint64_t generation,
|
||||
bool notify_native) = 0;
|
||||
virtual bool IsTextFocusSessionActive(uint64_t generation) = 0;
|
||||
virtual Status ReplaceFocusedTextFromEngine(
|
||||
uint64_t generation, std::string authoritative_utf8) = 0;
|
||||
virtual Status QueryCurrentTextBoxInfo(
|
||||
|
||||
@@ -431,13 +431,12 @@ Status RobloxTextSurfaceOverlay::RasterizeLocked() {
|
||||
static_cast<std::size_t>(width * height * 4), 0);
|
||||
const int frame_width = static_cast<int>(width);
|
||||
const int frame_height = static_cast<int>(height);
|
||||
// Use Roblox's horizontal text bounds directly. Inventing padding from
|
||||
// the field's width or position shifts text away from its native origin
|
||||
// and makes long lines scroll before they reach the field's actual edge.
|
||||
// Use Roblox's text bounds directly. Extra padding shifts the native text
|
||||
// origin, scrolls long lines too early and clips compact chat fields.
|
||||
const int clip_left = 0;
|
||||
const int clip_right = frame_width;
|
||||
const int clip_top = 3;
|
||||
const int clip_bottom = std::max(clip_top, frame_height - 3);
|
||||
const int clip_top = 0;
|
||||
const int clip_bottom = frame_height;
|
||||
const int available_width = std::max(1, clip_right - clip_left);
|
||||
const bool wrapped_layout =
|
||||
presentation.multiline || presentation.text_wrapped;
|
||||
|
||||
Reference in new issue
Block a user