Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 29 additions & 2 deletions src/qt/terminal_widget.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Qt terminal geometry follows the current font; semantics stay in the model.
// Qt terminal geometry follows the current font; semantics stay in the model.
#pragma once

#include "terminal_session.hpp"
Expand All @@ -16,6 +16,8 @@
#include <QtMath>
#include <QWidget>
#include <array>
#include <cstdio>
#include <cstdlib>

namespace termforge::qt {

Expand Down Expand Up @@ -135,11 +137,36 @@ class TerminalWidget final : public QWidget {
if (query == Qt::ImCursorPosition) return 0;
return QWidget::inputMethodQuery(query);
}
// Opt-in observation for the fixed-IME runs: records exactly which kind of
// input-method event arrived and the UTF-8 bytes it carried. Unset by
// default so ordinary runs touch no file.
void ime_log(const char* kind, const QString& text) {
static const char* path = std::getenv("TERMFORGE_QT_IME_LOG");
if (path == nullptr) return;
FILE* stream = std::fopen(path, "ab");
if (stream == nullptr) return;
const QByteArray bytes = text.toUtf8();
const auto& screen = model_.screen();
const QPoint origin = mapToGlobal(QPoint(0, 0));
std::fprintf(stream, "{\"kind\":\"%s\",\"bytes\":%d,\"utf8\":\"", kind, static_cast<int>(bytes.size()));
for (const char ch : bytes) std::fprintf(stream, "%02x", static_cast<unsigned char>(ch));
std::fprintf(stream, "\",\"row\":%d,\"column\":%d,\"caret_x\":%d,\"caret_y\":%d,\"caret_w\":%d,\"caret_h\":%d,\"origin_x\":%d,\"origin_y\":%d}\n",
screen.row, screen.column,
margin + screen.column * cell_width_, margin + screen.row * cell_height_,
cell_width_, cell_height_, origin.x(), origin.y());
std::fclose(stream);
}
void inputMethodEvent(QInputMethodEvent* event) override {
const QString preedit = event->preeditString();
if (preedit != preedit_) { preedit_ = preedit; update(); }
if (preedit != preedit_) {
if (!preedit.isEmpty()) ime_log("preedit", preedit);
else if (!preedit_.isEmpty()) ime_log("cancel", QString());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Distinguish composition commits from cancellations in the log

When logging is enabled, committing an active composition with an empty preedit and nonempty commit string produces both a cancel record and a commit record for the same event. This occurs in the existing src/qt/shell_smoke.cpp sequence that sends composing followed by committed; no cancellation actually occurs. Consequently, the diagnostic output cannot reliably distinguish successful composition completion from cancellation, undermining the IME evidence this change is intended to collect. Check the commit string before classifying an empty preedit as cancellation, or record the event's preedit and commit fields together without inferring a cancellation.

Useful? React with 👍 / 👎.

preedit_ = preedit;
update();
}
const QString commit = event->commitString();
if (!commit.isEmpty()) {
ime_log("commit", commit);
model_.send(commit.toUtf8());
preedit_.clear();
update();
Expand Down