Skip to content

Commit

Permalink
Emulate IMM32 vertical writing protocol in TSF
Browse files Browse the repository at this point in the history
mozc_renderer indeed has had logic to avoid its candidate window from
being placed over the composing text in vertical writing scenario.
This logic was, however, fully implemented only in Mozc's IMM32 DLLs.
Mozc's TIP modules have not yet propagated the same information to
mozc_renderer.  As a result, Mozc's candidate window always overwraps
composing text in the vertical writing mode, and Chromium ended up
implementing a workaround for this behavior [1].

With this commit, Mozc's TIP DLLs start filling CharacterPosition in
the same way as Mozc's IMM32 DLLs used to do in the vertical writing
mode.

Now the observable behavior in the vertical writing mode should be the
same as IMM32 Mozc.

Closes #362.

 [1]: https://chromium-review.googlesource.com/c/chromium/src/+/4023235

PiperOrigin-RevId: 573515844
  • Loading branch information
yukawa authored and hiroyuki-komatsu committed Oct 14, 2023
1 parent fe9665d commit 1212d91
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 6 deletions.
3 changes: 3 additions & 0 deletions src/protocol/renderer_command.proto
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ message RendererCommand {
optional Point top_left = 2;
optional uint32 line_height = 3;
optional Rectangle document_area = 4;
// A quick solution for vertical writing support.
// Strictly speaking, this is not part of IMECHARPOSITION in IMM32.
optional bool vertical_writing = 5;
}

// Visual information about mode indicator.
Expand Down
9 changes: 6 additions & 3 deletions src/renderer/win32/win32_renderer_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -763,9 +763,12 @@ double LayoutManager::GetScalingFactor(HWND window_handle) const {

LayoutManager::WritingDirection LayoutManager::GetWritingDirection(
const commands::RendererCommand_ApplicationInfo &app_info) {
// TODO(https://github.com/google/mozc/issues/362): Implement this for TSF.
// When fixing this, we also need to update Chromium.
// https://chromium-review.googlesource.com/c/chromium/src/+/4023235
const commands::RendererCommand::CharacterPosition &composition_target =
app_info.composition_target();
if (composition_target.has_vertical_writing()) {
return composition_target.vertical_writing() ? VERTICAL_WRITING
: HORIZONTAL_WRITING;
}
return WRITING_DIRECTION_UNSPECIFIED;
}

Expand Down
27 changes: 27 additions & 0 deletions src/win32/tip/tip_range_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ constexpr GUID kGuidPropInputscope = {
0x4a5b,
{0x9a, 0xf6, 0x59, 0x2a, 0x59, 0x5c, 0x77, 0x8d}};

// TSATTRID_Text_VerticalWriting
constexpr GUID kGuidAttrIdTextVerticalWriting = {
0x6bba8195,
0x046f,
0x4ea9,
{0xb3, 0x11, 0x97, 0xfd, 0x66, 0xc4, 0x27, 0x4b}};

HRESULT GetReadOnlyAppProperty(ITfRange *range, TfEditCookie read_cookie,
const GUID &guid, VARIANT *variant_addr) {
HRESULT result = S_OK;
Expand Down Expand Up @@ -214,6 +221,26 @@ HRESULT TipRangeUtil::GetInputScopes(ITfRange *range, TfEditCookie read_cookie,
return S_OK;
}

HRESULT TipRangeUtil::IsVerticalWriting(ITfRange *range,
TfEditCookie read_cookie,
bool *vertical_writing) {
if (vertical_writing == nullptr) {
return E_FAIL;
}
*vertical_writing = false;

wil::unique_variant variant;
HRESULT result = GetReadOnlyAppProperty(range,
read_cookie,
kGuidAttrIdTextVerticalWriting,
variant.reset_and_addressof());
if (FAILED(result)) {
return result;
}
*vertical_writing = (variant.vt == VT_BOOL && variant.boolVal != 0);
return S_OK;
}

bool TipRangeUtil::IsRangeCovered(TfEditCookie edit_cookie,
ITfRange *range_test, ITfRange *range_cover) {
HRESULT result = S_OK;
Expand Down
5 changes: 5 additions & 0 deletions src/win32/tip/tip_range_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ class TipRangeUtil {
static HRESULT GetInputScopes(ITfRange *range, TfEditCookie read_cookie,
std::vector<InputScope> *input_scopes);

// Retrieves whether the specified |range| is for vertical writing or not.
// Returns the general result code.
static HRESULT IsVerticalWriting(ITfRange *range, TfEditCookie read_cookie,
bool *vertical_writing);

// Checks whether or not |range_test| becomes a subset of |range_cover|.
static bool IsRangeCovered(TfEditCookie edit_cookie, ITfRange *range_test,
ITfRange *range_cover);
Expand Down
35 changes: 32 additions & 3 deletions src/win32/tip/tip_ui_handler_conventional.cc
Original file line number Diff line number Diff line change
Expand Up @@ -277,10 +277,39 @@ bool FillCharPosition(TipPrivateContext *private_context, ITfContext *context,
app_info->mutable_composition_target();
composition_target->set_position(0);

bool vertical_writing = false;
if (SUCCEEDED(TipRangeUtil::IsVerticalWriting(
target_range.get(), read_cookie, &vertical_writing))) {
composition_target->set_vertical_writing(vertical_writing);
}

RendererCommand::Point *point = composition_target->mutable_top_left();
point->set_x(text_rect.left);
point->set_y(text_rect.top);
composition_target->set_line_height(text_rect.bottom - text_rect.top);
if (vertical_writing) {
// [Vertical Writing]
// |
// +-----< (pt)
// | |
// |-----+
// | (cLineHeight)
// |
// |
// v
// (Base Line)
point->set_x(text_rect.right);
point->set_y(text_rect.top);
composition_target->set_line_height(text_rect.right - text_rect.left);
} else {
// [Horizontal Writing]
// (pt)
// v_____
// | |
// | | (cLineHeight)
// | |
// --+-----+----------> (Base Line)
point->set_x(text_rect.left);
point->set_y(text_rect.top);
composition_target->set_line_height(text_rect.bottom - text_rect.top);
}

RendererCommand::Rectangle *area =
composition_target->mutable_document_area();
Expand Down

0 comments on commit 1212d91

Please sign in to comment.