1
0
mirror of https://github.com/salvadordf/CEF4Delphi.git synced 2025-04-07 06:50:04 +02:00

Partial fix for issue #413 Chinese IME bug in OSR

This commit is contained in:
salvadordf 2022-04-23 16:49:11 +02:00
parent b94d03b678
commit 63bd707553
4 changed files with 148 additions and 147 deletions

View File

@ -124,6 +124,7 @@ type
{$IFDEF MSWINDOWS}
procedure CreateParams(var Params: TCreateParams); override;
procedure WndProc(var aMessage: TMessage); override;
procedure WMCEFInvalidate(var aMessage: TMessage); message CEF_INVALIDATE;
procedure WMEraseBkgnd(var aMessage : TWMEraseBkgnd); message WM_ERASEBKGND;
procedure WMTouch(var aMessage: TMessage); message WM_TOUCH;
procedure WMPointerDown(var aMessage: TMessage); message WM_POINTERDOWN;
@ -488,7 +489,7 @@ end;
function TBufferPanel.InvalidatePanel : boolean;
begin
{$IFDEF MSWINDOWS}
Result := HandleAllocated and PostMessage(Handle, CM_INVALIDATE, 0, 0);
Result := HandleAllocated and PostMessage(Handle, CEF_INVALIDATE, 0, 0);
{$ELSE}
Result := True;
TThread.ForceQueue(nil, @Invalidate);
@ -678,6 +679,11 @@ begin
end;
end;
procedure TBufferPanel.WMCEFInvalidate(var aMessage: TMessage);
begin
Invalidate;
end;
procedure TBufferPanel.WMEraseBkgnd(var aMessage : TWMEraseBkgnd);
begin
aMessage.Result := 1;
@ -762,6 +768,17 @@ begin
end;
procedure TBufferPanel.WMIMEComposition(var aMessage: TMessage);
const
// CEF uses UINT32_MAX to initialize the TCefRange parameters.
// FPC works fine with a high(integer) value but if we try to use
// integer(high(cardinal)) then it duplicates the result string.
// Delphi however works fine with integer(high(cardinal)) but it doesn't show
// any resul string if we use high(integer)
{$IFDEF FPC}
UINT32_MAX = high(integer);
{$ELSE}
UINT32_MAX = integer(high(cardinal));
{$ENDIF}
var
TempText : ustring;
TempRange : TCefRange;
@ -780,8 +797,8 @@ begin
begin
if assigned(FOnIMECommitText) then
begin
TempRange.from := high(Integer);
TempRange.to_ := high(Integer);
TempRange.from := UINT32_MAX;
TempRange.to_ := UINT32_MAX;
DoOnIMECommitText(TempText, @TempRange, 0);
end;
@ -793,8 +810,8 @@ begin
begin
if assigned(FOnIMESetComposition) then
begin
TempRange.from := high(Integer);
TempRange.to_ := high(Integer);
TempRange.from := UINT32_MAX;
TempRange.to_ := UINT32_MAX;
TempSelection.from := TempCompStart;
TempSelection.to_ := TempCompStart + length(TempText);

View File

@ -620,7 +620,6 @@ const
CEF_DOCKING_MODE_BOTTOM_LEFT = 3;
CEF_DOCKING_MODE_BOTTOM_RIGHT = 4;
CEF_DOCKING_MODE_CUSTOM = 5;
// /include/internal/cef_types.h (cef_show_state_t)
CEF_SHOW_STATE_NORMAL = 1;
CEF_SHOW_STATE_MINIMIZED = 2;
@ -704,6 +703,7 @@ const
CEF_SENTINEL_START = {$IFDEF MSWINDOWS}WM_APP +{$ENDIF} $A0A;
CEF_SENTINEL_DOCLOSE = {$IFDEF MSWINDOWS}WM_APP +{$ENDIF} $A0B;
CEF_BEFORECLOSE = {$IFDEF MSWINDOWS}WM_APP +{$ENDIF} $A0C;
CEF_INVALIDATE = {$IFDEF MSWINDOWS}WM_APP +{$ENDIF} $A0D;
// Lazarus and some old Delphi versions don't have these message contants
{$IF NOT DECLARED(WM_TOUCH)}

View File

@ -92,7 +92,7 @@ type
procedure GetCompositionInfo(imc : HIMC; aParam : LPARAM; var composition_text : ustring; var underlines : TCefCompositionUnderlineDynArray; var composition_start : integer);
function GetString(imc : HIMC; aParam : WParam; aType : integer; var aResult : ustring) : boolean;
{$IFDEF MSWINDOWS}
function IsSelectionAttribute(aAttribute : byte) : boolean;
function IsSelectionAttribute(aAttribute : AnsiChar) : boolean;
{$ENDIF}
procedure GetCompositionSelectionRange(imc : HIMC; var target_start, target_end : integer);
procedure GetCompositionUnderlines(imc : HIMC; target_start, target_end : integer; var underlines : TCefCompositionUnderlineDynArray);
@ -125,6 +125,12 @@ type
end;
// Original Chromium source code :
// https://source.chromium.org/chromium/chromium/src/+/main:ui/base/ime/win/imm32_manager.cc
// Original CEF source code :
// https://bitbucket.org/chromiumembedded/cef/src/master/tests/cefclient/browser/osr_ime_handler_win.cc
implementation
uses
@ -209,10 +215,7 @@ procedure TCEFOSRIMEHandler.GetCompositionInfo( imc : HIMC;
var underlines : TCefCompositionUnderlineDynArray;
var composition_start : integer);
var
TempStart : integer;
TempEnd : integer;
TempLen : integer;
i : integer;
TempTargetStart, TempTargetEnd, TempLen, i : integer;
begin
if (underlines <> nil) then
begin
@ -220,13 +223,13 @@ begin
underlines := nil;
end;
TempLen := length(composition_text);
TempStart := TempLen;
TempEnd := TempLen;
TempLen := length(composition_text);
TempTargetStart := TempLen;
TempTargetEnd := TempLen;
{$IFDEF MSWINDOWS}
if ((aParam and GCS_COMPATTR) <> 0) then
GetCompositionSelectionRange(imc, TempStart, TempEnd);
GetCompositionSelectionRange(imc, TempTargetStart, TempTargetEnd);
if ((aParam and CS_NOMOVECARET) = 0) and ((aParam and GCS_CURSORPOS) <> 0) then
composition_start := ImmGetCompositionString(imc, GCS_CURSORPOS, nil, 0)
@ -234,51 +237,51 @@ begin
composition_start := 0;
if ((aParam and GCS_COMPCLAUSE) <> 0) then
GetCompositionUnderlines(imc, TempStart, TempEnd, underlines);
GetCompositionUnderlines(imc, TempTargetStart, TempTargetEnd, underlines);
{$ENDIF}
if (underlines = nil) or (length(underlines) = 0) then
begin
i := 0;
if (TempStart > 0) then inc(i);
if (TempEnd > TempStart) then inc(i);
if (TempEnd < TempLen) then inc(i);
if (TempTargetStart > 0) then inc(i);
if (TempTargetEnd > TempTargetStart) then inc(i);
if (TempTargetEnd < TempLen) then inc(i);
if (i > 0) then
begin
SetLength(underlines, i);
i := 0;
if (TempStart > 0) then
if (TempTargetStart > 0) then
begin
underlines[i].color := DEFAULT_BLINK_UNDERLINE_COLOR;
underlines[i].background_color := DEFAULT_BLINK_BACKGROUND_COLOR;
underlines[i].range.from := 0;
underlines[i].range.to_ := TempStart;
underlines[i].range.to_ := TempTargetStart;
underlines[i].thick := 0;
underlines[i].style := DEFAULT_BLINK_UNDERLINE_STYLE;
inc(i);
end;
if (TempEnd > TempStart) then
if (TempTargetEnd > TempTargetStart) then
begin
underlines[i].color := DEFAULT_BLINK_UNDERLINE_COLOR;
underlines[i].background_color := DEFAULT_BLINK_BACKGROUND_COLOR;
underlines[i].range.from := TempStart;
underlines[i].range.to_ := TempEnd;
underlines[i].range.from := TempTargetStart;
underlines[i].range.to_ := TempTargetEnd;
underlines[i].thick := 1;
underlines[i].style := DEFAULT_BLINK_UNDERLINE_STYLE;
inc(i);
end;
if (TempEnd < TempLen) then
if (TempTargetEnd < TempLen) then
begin
underlines[i].color := DEFAULT_BLINK_UNDERLINE_COLOR;
underlines[i].background_color := DEFAULT_BLINK_BACKGROUND_COLOR;
underlines[i].range.from := TempEnd;
underlines[i].range.from := TempTargetEnd;
underlines[i].range.to_ := TempLen;
underlines[i].thick := 0;
underlines[i].style := DEFAULT_BLINK_UNDERLINE_STYLE;
@ -287,103 +290,89 @@ begin
end;
end;
function TCEFOSRIMEHandler.GetString(imc : HIMC; aParam : WParam; aType : integer; var aResult : ustring) : boolean;
function TCEFOSRIMEHandler.GetString( imc : HIMC;
aParam : WParam;
aType : integer;
var aResult : ustring) : boolean;
{$IFDEF MSWINDOWS}
var
TempBufferLen : integer;
TempBuffer : PWChar;
TempStringSize : integer;
TempBuffer : PWideChar;
{$ENDIF}
begin
Result := False;
{$IFDEF MSWINDOWS}
if ((aParam and aType) = 0) then exit;
{$IFDEF MSWINDOWS}
{$IFDEF FPC}
TempBufferLen := ImmGetCompositionStringW(imc, aType, nil, 0);
{$ELSE}
TempBufferLen := ImmGetCompositionString(imc, aType, nil, 0);
{$ENDIF}
TempStringSize := ImmGetCompositionStringW(imc, aType, nil, 0);
if (GetLastError <> 0) or (TempBufferLen <= 0) then exit;
{$ENDIF}
if (TempStringSize <= 0) then exit;
TempBuffer := nil;
TempBufferLen := TempBufferLen + SizeOf(wchar);
TempStringSize := TempStringSize + SizeOf(WideChar);
TempBuffer := nil;
try
try
GetMem(TempBuffer, TempBufferLen);
FillChar(TempBuffer^, TempBufferLen, 0);
{$IFDEF MSWINDOWS}
{$IFDEF FPC}
TempBufferLen := ImmGetCompositionStringW(imc, aType, TempBuffer, TempBufferLen);
{$ELSE}
TempBufferLen := ImmGetCompositionString(imc, aType, TempBuffer, TempBufferLen);
{$ENDIF}
{$ENDIF}
if (TempBufferLen > 0) then
begin
aResult := TempBuffer;
Result := True;
end;
GetMem(TempBuffer, TempStringSize);
FillChar(TempBuffer^, TempStringSize, 0);
ImmGetCompositionStringW(imc, aType, TempBuffer, TempStringSize);
aResult := TempBuffer;
Result := True;
except
on e : exception do
if CustomExceptionHandler('TCEFOSRIMEHandler.GetString', e) then raise;
end;
finally
if (TempBuffer <> nil) then FreeMem(TempBuffer);
if (TempBuffer <> nil) then
FreeMem(TempBuffer);
end;
{$ENDIF}
end;
{$IFDEF MSWINDOWS}
function TCEFOSRIMEHandler.IsSelectionAttribute(aAttribute : byte) : boolean;
function TCEFOSRIMEHandler.IsSelectionAttribute(aAttribute : AnsiChar) : boolean;
begin
Result := (aAttribute = ATTR_TARGET_CONVERTED) or
(aAttribute = ATTR_TARGET_NOTCONVERTED);
Result := (ord(aAttribute) = ATTR_TARGET_CONVERTED) or
(ord(aAttribute) = ATTR_TARGET_NOTCONVERTED);
end;
{$ENDIF}
procedure TCEFOSRIMEHandler.GetCompositionSelectionRange(imc : HIMC; var target_start, target_end : integer);
{$IFDEF MSWINDOWS}
var
i : integer;
TempBufferLen : integer;
TempBuffer : array of byte;
i, TempStart, TempEnd, TempBufferLen : integer;
TempBuffer : array of AnsiChar;
{$ENDIF}
begin
TempBuffer := nil;
{$IFDEF MSWINDOWS}
TempBuffer := nil;
try
try
TempBufferLen := ImmGetCompositionString(imc, GCS_COMPATTR, nil, 0);
TempBufferLen := ImmGetCompositionStringW(imc, GCS_COMPATTR, nil, 0);
if (GetLastError = 0) and (TempBufferLen > 0) then
if (TempBufferLen > 0) then
begin
SetLength(TempBuffer, TempBufferLen);
for i := 0 to pred(TempBufferLen) do TempBuffer[i] := 0;
for i := 0 to pred(TempBufferLen) do TempBuffer[i] := #0;
TempBufferLen := ImmGetCompositionString(imc, GCS_COMPATTR, @TempBuffer[0], TempBufferLen);
TempBufferLen := ImmGetCompositionStringW(imc, GCS_COMPATTR, @TempBuffer[0], TempBufferLen);
if (TempBufferLen > 0) then
begin
i := 0;
while (i < TempBufferLen) do
if IsSelectionAttribute(TempBuffer[i]) then
begin
target_start := i;
break;
end
else
inc(i);
TempStart := 0;
while (TempStart < TempBufferLen) do
if IsSelectionAttribute(TempBuffer[TempStart]) then
break
else
inc(TempStart);
while (i < TempBufferLen) do
if not(IsSelectionAttribute(TempBuffer[i])) then
begin
target_end := i;
break;
end
else
inc(i);
end;
TempEnd := TempStart;
while (TempEnd < TempBufferLen) do
if not(IsSelectionAttribute(TempBuffer[TempEnd])) then
break
else
inc(TempEnd);
target_start := TempStart;
target_end := TempEnd;
end;
except
on e : exception do
@ -403,57 +392,52 @@ procedure TCEFOSRIMEHandler.GetCompositionUnderlines( imc : HIMC;
target_start : integer;
target_end : integer;
var underlines : TCefCompositionUnderlineDynArray);
{$IFDEF MSWINDOWS}
var
i, j, TempSize : integer;
TempUndLen : integer;
TempBufferLen : integer;
TempLen : integer;
TempBuffer : array of cardinal;
{$ENDIF}
begin
TempBuffer := nil;
{$IFDEF MSWINDOWS}
TempBuffer := nil;
try
try
TempBufferLen := ImmGetCompositionString(imc, GCS_COMPCLAUSE, nil, 0);
TempSize := ImmGetCompositionStringW(imc, GCS_COMPCLAUSE, nil, 0);
TempLen := TempSize div SizeOf(cardinal);
if (GetLastError = 0) and (TempBufferLen > 0) then
if (TempLen > 0) then
begin
TempSize := TempBufferLen div SizeOf(cardinal);
SetLength(TempBuffer, TempSize);
for i := 0 to pred(TempSize) do TempBuffer[i] := 0;
SetLength(TempBuffer, TempLen);
for i := 0 to pred(TempLen) do TempBuffer[i] := 0;
TempBufferLen := ImmGetCompositionString(imc, GCS_COMPCLAUSE, @TempBuffer[0], TempBufferLen);
ImmGetCompositionStringW(imc, GCS_COMPCLAUSE, @TempBuffer[0], TempSize);
if (TempBufferLen > 0) then
if (underlines <> nil) then
TempUndLen := length(underlines)
else
TempUndLen := 0;
SetLength(underlines, TempUndLen + pred(TempSize));
i := 0;
while (i < pred(TempLen)) do
begin
TempSize := TempBufferLen div SizeOf(cardinal);
j := i + TempUndLen;
if (underlines <> nil) then
TempUndLen := length(underlines)
underlines[j].range.from := TempBuffer[i];
underlines[j].range.to_ := TempBuffer[succ(i)];
underlines[j].color := DEFAULT_BLINK_UNDERLINE_COLOR;
underlines[j].background_color := DEFAULT_BLINK_BACKGROUND_COLOR;
underlines[j].style := DEFAULT_BLINK_UNDERLINE_STYLE;
if (underlines[j].range.from >= target_start) and
(underlines[j].range.to_ <= target_end) then
underlines[j].thick := 1
else
TempUndLen := 0;
underlines[j].thick := 0;
SetLength(underlines, TempUndLen + pred(TempSize));
i := 0;
while (i < pred(TempSize)) do
begin
j := i + TempUndLen;
underlines[j].range.from := TempBuffer[i];
underlines[j].range.to_ := TempBuffer[succ(i)];
underlines[j].color := DEFAULT_BLINK_UNDERLINE_COLOR;
underlines[j].background_color := DEFAULT_BLINK_BACKGROUND_COLOR;
underlines[j].style := DEFAULT_BLINK_UNDERLINE_STYLE;
if (underlines[j].range.from >= target_start) and
(underlines[j].range.to_ <= target_end) then
underlines[j].thick := 1
else
underlines[j].thick := 0;
inc(i);
end;
inc(i);
end;
end;
except
@ -679,10 +663,11 @@ end;
procedure TCEFOSRIMEHandler.MoveImeWindow;
{$IFDEF MSWINDOWS}
var
TempRect : TCefRect;
TempLocation : integer;
TempIMC : HIMC;
TempCandidate : TCandidateForm;
TempRect : TCefRect;
TempLocation : integer;
TempIMC : HIMC;
TempCandidatePos : TCandidateForm;
TempCandidateExc : TCandidateForm;
const
CARET_MARGIN = 1;
{$ENDIF}
@ -717,16 +702,16 @@ begin
try
if (PrimaryLangID = LANG_CHINESE) then
begin
TempCandidate.dwIndex := 0;
TempCandidate.dwStyle := CFS_CANDIDATEPOS;
TempCandidate.ptCurrentPos.X := TempRect.x;
TempCandidate.ptCurrentPos.Y := TempRect.y;
TempCandidate.rcArea.Left := 0;
TempCandidate.rcArea.Top := 0;
TempCandidate.rcArea.Right := 0;
TempCandidate.rcArea.Bottom := 0;
TempCandidatePos.dwIndex := 0;
TempCandidatePos.dwStyle := CFS_CANDIDATEPOS;
TempCandidatePos.ptCurrentPos.X := TempRect.x;
TempCandidatePos.ptCurrentPos.Y := TempRect.y;
TempCandidatePos.rcArea.Left := 0;
TempCandidatePos.rcArea.Top := 0;
TempCandidatePos.rcArea.Right := 0;
TempCandidatePos.rcArea.Bottom := 0;
ImmSetCandidateWindow(TempIMC, @TempCandidate);
ImmSetCandidateWindow(TempIMC, @TempCandidatePos);
end;
if FSystemCaret then
@ -735,20 +720,19 @@ begin
else SetCaretPos(TempRect.x, TempRect.y);
end;
if (PrimaryLangID = LANG_KOREAN) then
TempRect.y := TempRect.y + CARET_MARGIN;
TempCandidate.dwIndex := 0;
TempCandidate.dwStyle := CFS_EXCLUDE;
TempCandidate.ptCurrentPos.X := TempRect.x;
TempCandidate.ptCurrentPos.Y := TempRect.y;
TempCandidate.rcArea.Left := TempRect.x;
TempCandidate.rcArea.Top := TempRect.y;
TempCandidate.rcArea.Right := TempRect.x + TempRect.width;
TempCandidate.rcArea.Bottom := TempRect.y + TempRect.height;
TempCandidateExc.dwIndex := 0;
TempCandidateExc.dwStyle := CFS_EXCLUDE;
TempCandidateExc.ptCurrentPos.X := TempRect.x;
TempCandidateExc.ptCurrentPos.Y := TempRect.y;
TempCandidateExc.rcArea.Left := TempRect.x;
TempCandidateExc.rcArea.Top := TempRect.y;
TempCandidateExc.rcArea.Right := TempRect.x + TempRect.width;
TempCandidateExc.rcArea.Bottom := TempRect.y + TempRect.height;
ImmSetCandidateWindow(TempIMC, @TempCandidate);
ImmSetCandidateWindow(TempIMC, @TempCandidateExc);
finally
ImmReleaseContext(FHWND, TempIMC);
end;

View File

@ -2,7 +2,7 @@
"UpdateLazPackages" : [
{
"ForceNotify" : true,
"InternalVersion" : 388,
"InternalVersion" : 389,
"Name" : "cef4delphi_lazarus.lpk",
"Version" : "100.0.24.0"
}