1
0
mirror of https://github.com/salvadordf/CEF4Delphi.git synced 2025-09-30 21:28:55 +02:00

Fixed IME in GTK3 for Lazarus

Only for browsers in OSR mode.
This commit is contained in:
Salvador Díaz Fau
2025-08-26 17:02:21 +02:00
parent 68d581f8b2
commit f32b44aa31
3 changed files with 96 additions and 29 deletions

View File

@@ -207,6 +207,12 @@ type
/// </summary> /// </summary>
function ConnectSignals: boolean; function ConnectSignals: boolean;
{$ENDIF} {$ENDIF}
{$IFDEF LCLGTK3}
/// <summary>
/// This is just a workaround for the missing implementation of SendMessage in GTK3. Don't use!
/// </summary>
procedure SendMessage(var aMessage : TMessage);
{$ENDIF}
/// <summary> /// <summary>
/// Returns the scanline size. /// Returns the scanline size.
@@ -675,6 +681,15 @@ begin
end; end;
{$ENDIF} {$ENDIF}
{$IFDEF LCLGTK3}
// This is just a workaround for the missing implementation of SendMessage in GTK3.
procedure TBufferPanel.SendMessage(var aMessage : TMessage);
begin
if (aMessage.Msg = LM_IM_COMPOSITION) and Focused then
WMIMEComposition(aMessage);
end;
{$ENDIF}
procedure TBufferPanel.CreateIMEHandler; procedure TBufferPanel.CreateIMEHandler;
begin begin
{$IFDEF MSWINDOWS} {$IFDEF MSWINDOWS}

View File

@@ -25,11 +25,11 @@ type
public public
constructor Create(aPanel : TCustomPanel); constructor Create(aPanel : TCustomPanel);
destructor Destroy; override; destructor Destroy; override;
procedure CreateContext; function CreateContext : boolean;
procedure DestroyContext; procedure DestroyContext;
procedure SetClientWindow; procedure SetClientWindow;
procedure ResetClientWindow; procedure ResetClientWindow;
procedure ConnectSignals; function ConnectSignals : boolean;
procedure Focus; procedure Focus;
procedure Blur; procedure Blur;
procedure Reset; procedure Reset;
@@ -51,7 +51,29 @@ implementation
uses uses
{$IF DEFINED(LCLGTK2) or DEFINED(LCLGTK3)}pango,{$ENDIF} {$IF DEFINED(LCLGTK2) or DEFINED(LCLGTK3)}pango,{$ENDIF}
{$IFDEF FPC}LCLType, LCLIntf, LMessages,{$ENDIF} {$IFDEF FPC}LCLType, LCLIntf, LMessages,{$ENDIF}
SysUtils; {$IFDEF LCLGTK3}uCEFBufferPanel,{$ENDIF}
SysUtils, uCEFMiscFunctions;
{$IFDEF LCLGTK3}
// This is just a workaround for the missing implementation of SendMessage in GTK3.
function SendMessage(HandleWnd: HWND; Msg: Cardinal; wParam: WParam; lParam: LParam): LResult;
var
LMessage : TLMessage;
LPanel : TBufferPanel;
begin
LMessage.Msg := Msg;
LMessage.WParam := WParam;
LMessage.LParam := LParam;
LMessage.Result := 0;
LPanel := TBufferPanel(HandleWnd);
if (LPanel <> nil) then
LPanel.SendMessage(LMessage);
Result := LMessage.Result;
end;
{$ENDIF}
{$IF DEFINED(LCLGTK2) or DEFINED(LCLGTK3)} {$IF DEFINED(LCLGTK2) or DEFINED(LCLGTK3)}
procedure gtk_commit_cb({%H-}context: PGtkIMContext; const Str: Pgchar; {%H-}Data: Pointer); cdecl; procedure gtk_commit_cb({%H-}context: PGtkIMContext; const Str: Pgchar; {%H-}Data: Pointer); cdecl;
@@ -126,14 +148,19 @@ begin
FForm := nil; FForm := nil;
end; end;
procedure TCEFLinuxOSRIMEHandler.CreateContext; function TCEFLinuxOSRIMEHandler.CreateContext : boolean;
begin begin
Result := False;
{$IF DEFINED(LCLGTK2) or DEFINED(LCLGTK3)} {$IF DEFINED(LCLGTK2) or DEFINED(LCLGTK3)}
if not(assigned(FIMContext)) then if not(assigned(FIMContext)) then
begin begin
FIMContext := gtk_im_multicontext_new(); FIMContext := gtk_im_multicontext_new();
if assigned(FIMContext) then
begin
SetClientWindow; SetClientWindow;
ConnectSignals; Result := ConnectSignals;
end;
end; end;
{$ENDIF} {$ENDIF}
end; end;
@@ -152,18 +179,18 @@ end;
procedure TCEFLinuxOSRIMEHandler.SetClientWindow; procedure TCEFLinuxOSRIMEHandler.SetClientWindow;
{$IF DEFINED(LCLGTK2) or DEFINED(LCLGTK3)} {$IF DEFINED(LCLGTK2) or DEFINED(LCLGTK3)}
var var
TempWidget : PGtkWidget; TempWindow : PGdkWindow;
{$ENDIF} {$ENDIF}
begin begin
if Initialized then if Initialized then
begin begin
{$IFDEF LCLGTK2} {$IFDEF LCLGTK2}
TempWidget := PGtkWidget(FForm.Handle); TempWindow := PGtkWidget(FForm.Handle)^.window;
gtk_im_context_set_client_window(FIMContext, TempWidget^.window); gtk_im_context_set_client_window(FIMContext, TempWindow);
{$ENDIF} {$ENDIF}
{$IFDEF LCLGTK3} {$IFDEF LCLGTK3}
TempWidget := TGtk3Widget(FForm.Handle).Widget; TempWindow := TGtk3Widget(FForm.Handle).Widget^.window;
gtk_im_context_set_client_window(FIMContext, TempWidget^.window); gtk_im_context_set_client_window(FIMContext, TempWindow);
{$ENDIF} {$ENDIF}
end; end;
end; end;
@@ -179,23 +206,48 @@ begin
end; end;
end; end;
procedure TCEFLinuxOSRIMEHandler.ConnectSignals; function TCEFLinuxOSRIMEHandler.ConnectSignals: boolean;
var
TempHandlerID1, TempHandlerID2, TempHandlerID3, TempHandlerID4 : gulong;
{$IF DEFINED(LCLGTK2) or DEFINED(LCLGTK3)}
TempData : GPointer;
{$ENDIF}
begin begin
TempHandlerID1 := 0;
TempHandlerID2 := 0;
TempHandlerID3 := 0;
TempHandlerID4 := 0;
try
try
if Initialized then if Initialized then
begin begin
{$IFDEF LCLGTK3} {$IFDEF LCLGTK3}
g_signal_connect_data(PGObject(@FIMContext), 'commit', TGCallback(@gtk_commit_cb), GPointer(FPanel.Handle), nil, G_CONNECT_DEFAULT); // This should be the data passed to the callback. We'll enable this line as soon as Lazarus implements SendMessage in GTK3.
g_signal_connect_data(PGObject(@FIMContext), 'preedit-start', TGCallback(@gtk_preedit_start_cb), GPointer(FPanel.Handle), nil, G_CONNECT_DEFAULT); //TempData := GPointer(TGtk3Widget(FPanel.Handle).Widget);
g_signal_connect_data(PGObject(@FIMContext), 'preedit-end', TGCallback(@gtk_preedit_end_cb), GPointer(FPanel.Handle), nil, G_CONNECT_DEFAULT); TempData := GPointer(FPanel);
g_signal_connect_data(PGObject(@FIMContext), 'preedit-changed', TGCallback(@gtk_preedit_changed_cb), GPointer(FPanel.Handle), nil, G_CONNECT_DEFAULT);
TempHandlerID1 := g_signal_connect_data(PGObject(FIMContext), 'commit', TGCallback(@gtk_commit_cb), TempData, nil, G_CONNECT_DEFAULT);
TempHandlerID2 := g_signal_connect_data(PGObject(FIMContext), 'preedit-start', TGCallback(@gtk_preedit_start_cb), TempData, nil, G_CONNECT_DEFAULT);
TempHandlerID3 := g_signal_connect_data(PGObject(FIMContext), 'preedit-end', TGCallback(@gtk_preedit_end_cb), TempData, nil, G_CONNECT_DEFAULT);
TempHandlerID4 := g_signal_connect_data(PGObject(FIMContext), 'preedit-changed', TGCallback(@gtk_preedit_changed_cb), TempData, nil, G_CONNECT_DEFAULT);
{$ENDIF} {$ENDIF}
{$IFDEF LCLGTK2} {$IFDEF LCLGTK2}
g_signal_connect(G_OBJECT(FIMContext), 'commit', G_CALLBACK(@gtk_commit_cb), GPointer(FPanel.Handle)); TempData := GPointer(FPanel.Handle);
g_signal_connect(G_OBJECT(FIMContext), 'preedit-start', G_CALLBACK(@gtk_preedit_start_cb), GPointer(FPanel.Handle));
g_signal_connect(G_OBJECT(FIMContext), 'preedit-end', G_CALLBACK(@gtk_preedit_end_cb), GPointer(FPanel.Handle)); TempHandlerID1 := g_signal_connect(G_OBJECT(FIMContext), 'commit', G_CALLBACK(@gtk_commit_cb), TempData);
g_signal_connect(G_OBJECT(FIMContext), 'preedit-changed', G_CALLBACK(@gtk_preedit_changed_cb), GPointer(FPanel.Handle)); TempHandlerID2 := g_signal_connect(G_OBJECT(FIMContext), 'preedit-start', G_CALLBACK(@gtk_preedit_start_cb), TempData);
TempHandlerID3 := g_signal_connect(G_OBJECT(FIMContext), 'preedit-end', G_CALLBACK(@gtk_preedit_end_cb), TempData);
TempHandlerID4 := g_signal_connect(G_OBJECT(FIMContext), 'preedit-changed', G_CALLBACK(@gtk_preedit_changed_cb), TempData);
{$ENDIF} {$ENDIF}
end; end;
except
on e : exception do
if CustomExceptionHandler('TCEFLinuxOSRIMEHandler.ConnectSignals', e) then raise;
end;
finally
Result := (TempHandlerID1 > 0) and (TempHandlerID2 > 0) and (TempHandlerID3 > 0) and (TempHandlerID4 > 0);
end;
end; end;
procedure TCEFLinuxOSRIMEHandler.Focus; procedure TCEFLinuxOSRIMEHandler.Focus;

View File

@@ -2,7 +2,7 @@
"UpdateLazPackages" : [ "UpdateLazPackages" : [
{ {
"ForceNotify" : true, "ForceNotify" : true,
"InternalVersion" : 772, "InternalVersion" : 773,
"Name" : "cef4delphi_lazarus.lpk", "Name" : "cef4delphi_lazarus.lpk",
"Version" : "139.0.28" "Version" : "139.0.28"
} }