diff --git a/source/uCEFBufferPanel.pas b/source/uCEFBufferPanel.pas index 0c49787a..5fa75cac 100644 --- a/source/uCEFBufferPanel.pas +++ b/source/uCEFBufferPanel.pas @@ -124,6 +124,7 @@ TBufferPanel = class(TCustomPanel) {$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 @@ function TBufferPanel.SaveToFile(const aFilename : string) : boolean; 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 @@ procedure TBufferPanel.WndProc(var aMessage: TMessage); 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 @@ procedure TBufferPanel.WMIMESetContext(var aMessage: TMessage); 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 @@ procedure TBufferPanel.WMIMEComposition(var aMessage: TMessage); 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 @@ procedure TBufferPanel.WMIMEComposition(var aMessage: TMessage); 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); diff --git a/source/uCEFConstants.pas b/source/uCEFConstants.pas index 12f309e1..ee452d66 100644 --- a/source/uCEFConstants.pas +++ b/source/uCEFConstants.pas @@ -620,7 +620,6 @@ interface 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 @@ interface 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)} diff --git a/source/uCEFOSRIMEHandler.pas b/source/uCEFOSRIMEHandler.pas index 97c7a5b5..c7108933 100644 --- a/source/uCEFOSRIMEHandler.pas +++ b/source/uCEFOSRIMEHandler.pas @@ -92,7 +92,7 @@ TCEFOSRIMEHandler = class 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 @@ TCEFOSRIMEHandler = class 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 @@ procedure TCEFOSRIMEHandler.GetCompositionInfo( imc : HIMC; 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 @@ procedure TCEFOSRIMEHandler.GetCompositionInfo( imc : HIMC; 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 @@ procedure TCEFOSRIMEHandler.GetCompositionInfo( imc : HIMC; 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; - - TempBufferLen := ImmGetCompositionString(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); - - while (i < TempBufferLen) do - if not(IsSelectionAttribute(TempBuffer[i])) then - begin - target_end := i; - break; - end - else - inc(i); - end; + for i := 0 to pred(TempBufferLen) do TempBuffer[i] := #0; + + TempBufferLen := ImmGetCompositionStringW(imc, GCS_COMPATTR, @TempBuffer[0], TempBufferLen); + + TempStart := 0; + while (TempStart < TempBufferLen) do + if IsSelectionAttribute(TempBuffer[TempStart]) then + break + else + inc(TempStart); + + 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; - - TempBufferLen := ImmGetCompositionString(imc, GCS_COMPCLAUSE, @TempBuffer[0], TempBufferLen); + SetLength(TempBuffer, TempLen); + for i := 0 to pred(TempLen) do TempBuffer[i] := 0; - if (TempBufferLen > 0) then - begin - TempSize := TempBufferLen div SizeOf(cardinal); - - if (underlines <> nil) then - TempUndLen := length(underlines) - else - TempUndLen := 0; + ImmGetCompositionStringW(imc, GCS_COMPCLAUSE, @TempBuffer[0], TempSize); - SetLength(underlines, TempUndLen + pred(TempSize)); - i := 0; + if (underlines <> nil) then + TempUndLen := length(underlines) + else + TempUndLen := 0; - while (i < pred(TempSize)) do - begin - j := i + TempUndLen; + SetLength(underlines, TempUndLen + pred(TempSize)); + i := 0; + while (i < pred(TempLen)) 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; + 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; + 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 @@ procedure TCEFOSRIMEHandler.ChangeCompositionRange(const selection_range : TCef 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 @@ procedure TCEFOSRIMEHandler.MoveImeWindow; 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; - - ImmSetCandidateWindow(TempIMC, @TempCandidate); + 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, @TempCandidatePos); end; if FSystemCaret then @@ -735,20 +720,19 @@ procedure TCEFOSRIMEHandler.MoveImeWindow; 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; diff --git a/update_CEF4Delphi.json b/update_CEF4Delphi.json index b653cf56..a53cc61f 100644 --- a/update_CEF4Delphi.json +++ b/update_CEF4Delphi.json @@ -2,7 +2,7 @@ "UpdateLazPackages" : [ { "ForceNotify" : true, - "InternalVersion" : 388, + "InternalVersion" : 389, "Name" : "cef4delphi_lazarus.lpk", "Version" : "100.0.24.0" }