How about this?
Index: components/synedit/synedit.pp
===================================================================
--- components/synedit/synedit.pp (revision 47591)
+++ components/synedit/synedit.pp (working copy)
@@ -1142,6 +1142,10 @@
property OnSpecialLineColors: TSpecialLineColorsEvent read FOnSpecialLineColors write SetSpecialLineColors; deprecated;
property OnSpecialLineMarkup: TSpecialLineMarkupEvent read FOnSpecialLineMarkup write SetSpecialLineMarkup;
property OnStatusChange: TStatusChangeEvent read fOnStatusChange write fOnStatusChange;
+{$ifdef LCLGtk2}
+ protected
+ procedure GTK_IMComposition(var Message:TMessage); message LM_IM_COMPOSITION;
+{$endif}
end;
TSynEdit = class(TCustomSynEdit)
@@ -4029,6 +4033,26 @@
Result := FMarkupManager.Count;
end;
+{$ifdef LCLGtk2}
+procedure TCustomSynEdit.GTK_IMComposition(var Message: TMessage);
+var
+ IMStr:TUTF8Char;
+begin
+ if (not ReadOnly) then
+ begin
+ // delete previous character by selection
+ if Message.WParam and GTK_IM_FLAG_REPLACE<>0 then
+ CommandProcessor(ecSelLeft,#0,nil);
+ // valid string at composition & commit
+ if Message.WParam and (GTK_IM_FLAG_START or GTK_IM_FLAG_END)=0 then
+ begin
+ IMStr:=pchar(Message.LParam);
+ UTF8KeyPress(IMStr);
+ end;
+ end;
+end;
+{$endif}
+
procedure TCustomSynEdit.SetCaretTypeSize(AType: TSynCaretType; AWidth, AHeight, AXOffs,
AYOffs: Integer);
begin
Index: lcl/interfaces/gtk2/gtk2globals.pp
===================================================================
--- lcl/interfaces/gtk2/gtk2globals.pp (revision 47591)
+++ lcl/interfaces/gtk2/gtk2globals.pp (working copy)
@@ -78,6 +78,8 @@
im_context: PGtkIMContext = nil;
im_context_widget: PGtkWidget = nil;
im_context_string: string = '';
+ im_context_use: Boolean = False; //DW
+ im_context_skipDelete: Boolean = False;
procedure ResetDefaultIMContext;
@@ -424,6 +426,8 @@
end;
im_context_widget:=nil;
im_context_string:='';
+ im_context_use:=False; //DW
+ im_context_skipDelete:=False;
end;
procedure AddCharsetEncoding(CharSet: Byte; CharSetReg, CharSetCod: CharSetStr;
Index: lcl/interfaces/gtk2/gtk2proc.inc
===================================================================
--- lcl/interfaces/gtk2/gtk2proc.inc (revision 47591)
+++ lcl/interfaces/gtk2/gtk2proc.inc (working copy)
@@ -2000,7 +2000,8 @@
end;
Exit;
end;
- Result := (AEvent^.Length > 0) or (GetSpecialChar <> #0);
+ //DW
+ Result := ((not im_context_use) and (AEvent^.Length > 0)) or (GetSpecialChar <> #0);
end;
function KeyAlreadyHandledByGtk: boolean;
@@ -2007,7 +2008,7 @@
begin
Result := false;
if AWidget = nil then exit;
-
+
if GtkWidgetIsA(AWidget, gtk_entry_get_type)
then begin
// the gtk_entry handles the following keys
@@ -2361,7 +2362,7 @@
Msg.KeyData := CommonKeyData or (Flags shl 16) or $0001 {TODO: repeatcount};
- if not KeyAlreadyHandledByGtk
+ if (not KeyAlreadyHandledByGtk) and (not im_context_use)
then begin
// send the (Sys)KeyDown message directly to the LCL
NotifyApplicationUserInput(TControl(TargetObj), Msg.Msg);
@@ -2433,7 +2434,10 @@
begin
OldCharacter := Character;
// send the key after navigation keys were handled
- Result := TWinControl(LCLObject).IntfUTF8KeyPress(Character, 1, SysKey);
+ if not im_context_use then
+ Result := TWinControl(LCLObject).IntfUTF8KeyPress(Character, 1, SysKey)
+ else
+ Result:=True;
if Result or (Character = '') then
// dont' stop key event here, just clear it since we need a keyUp event
ClearKey
Index: lcl/interfaces/gtk2/gtk2widgetset.inc
===================================================================
--- lcl/interfaces/gtk2/gtk2widgetset.inc (revision 47591)
+++ lcl/interfaces/gtk2/gtk2widgetset.inc (working copy)
@@ -216,11 +216,88 @@
procedure gtk_commit_cb ({%H-}context: PGtkIMContext; const Str: Pgchar;
{%H-}Data: Pointer); cdecl;
+var
+ Control:TWinControl;
+ Flag:WPARAM;
begin
//DebugLn(['gtk_commit_cb ',dbgstr(Str),'="',Str,'"']);
im_context_string:=Str;
+ { Handle commit string at ending composition,
+ it cannot handled by HandleGTKKeyUpDown }
+ if im_context_use and (im_context_widget<>nil) and (im_context_string<>'') and
+ gtk_widget_is_focus(im_context_widget) then
+ begin
+ Control:=TWinControl(GetNearestLCLObject(im_context_widget));
+ Flag:=GTK_IM_FLAG_COMMIT;
+ if not im_context_skipDelete then
+ Flag:=Flag or GTK_IM_FLAG_REPLACE;
+ SendMessage(Control.Handle,LM_IM_COMPOSITION,Flag,LPARAM(pchar(im_context_string)));
+ im_context_string:='';
+ im_context_skipDelete:=True;
+ end;
end;
+procedure gtk_preedit_start_cb({%H-}context: PGtkIMContext; {%H-}Data: Pointer); cdecl;
+var
+ control:TWinControl;
+ Flag:WPARAM;
+begin
+ if (im_context_widget<>nil) and
+ (gtk_widget_is_focus(im_context_widget)) and
+ (GetNearestLCLObject(im_context_widget) is TCustomControl) then
+ begin
+ im_context_use:=True;
+ im_context_skipDelete:=True;
+ control:=TWinControl(GetNearestLCLObject(im_context_widget));
+ Flag:=GTK_IM_FLAG_START;
+ SendMessage(Control.Handle,LM_IM_COMPOSITION,Flag,LPARAM(Data));
+ end else
+ im_context_use:=False;
+end;
+
+procedure gtk_preedit_end_cb({%H-}context: PGtkIMContext; {%H-}Data: Pointer); cdecl;
+var
+ control:TWinControl;
+ Flag:WPARAM;
+begin
+ im_context_use:=False;
+ if (im_context_widget<>nil) and
+ (gtk_widget_is_focus(im_context_widget)) and
+ (GetNearestLCLObject(im_context_widget) is TCustomControl) then
+ begin
+ im_context_skipDelete:=True;
+ control:=TWinControl(GetNearestLCLObject(im_context_widget));
+ Flag:=GTK_IM_FLAG_END;
+ SendMessage(control.Handle,LM_IM_COMPOSITION,Flag,LPARAM(Data));
+ end;
+end;
+
+procedure gtk_preedit_changed_cb({%H-}context:PGtkIMContext; {%H-}Data:Pointer); cdecl;
+var
+ str:Pgchar;
+ pangoattr:PPangoAttrList;
+ pos:gint;
+ control:TWinControl;
+ Flag:WPARAM;
+begin
+ if im_context_use and (im_context_widget<>nil) and
+ gtk_widget_is_focus(im_context_widget) then
+ begin
+ control:=TWinControl(GetNearestLCLObject(im_context_widget));
+ pos:=1;
+ gtk_im_context_get_preedit_string(context,@str,pangoattr,@pos);
+ im_context_string:=str;
+ g_free(str);
+ pango_attr_list_unref(pangoattr);
+ Flag:=GTK_IM_FLAG_COMPOSITION;
+ if (not im_context_skipDelete) and (Length(im_context_string)>0) then begin
+ Flag:=Flag or GTK_IM_FLAG_REPLACE;
+ end else
+ im_context_skipDelete:=False;
+ SendMessage(control.Handle,LM_IM_COMPOSITION,Flag,LPARAM(pchar(im_context_string)));
+ end;
+end;
+
{$IfNDef GTK2_2}
procedure gtkTreeSelectionCountSelectedRows({%H-}model : PGtkTreeModel; {%H-}path : PGtkTreePath;
{%H-}iter : PGtkTreeIter; data : PGint); cdecl;
@@ -985,6 +1062,13 @@
im_context:=gtk_im_multicontext_new;
g_signal_connect (G_OBJECT (im_context), 'commit',
G_CALLBACK (@gtk_commit_cb), nil);
+ //DW
+ g_signal_connect (G_OBJECT (im_context), 'preedit-start',
+ G_CALLBACK (@gtk_preedit_start_cb), nil);
+ g_signal_connect (G_OBJECT (im_context), 'preedit-end',
+ G_CALLBACK (@gtk_preedit_end_cb), nil);
+ g_signal_connect (G_OBJECT (im_context), 'preedit-changed',
+ G_CALLBACK (@gtk_preedit_changed_cb), nil);
{$IFDEF HASX}
if IsNoTransientWM then
begin
Index: lcl/lmessages.pp
===================================================================
--- lcl/lmessages.pp (revision 47591)
+++ lcl/lmessages.pp (working copy)
@@ -93,7 +93,15 @@
LM_INTERFACELAST = LM_LCL + 199;
LM_UNKNOWN = LM_INTERFACELAST + 1;
+ LM_IM_COMPOSITION = LM_UNKNOWN + 1; // gtk IM
+ // GTK IM Flags
+ GTK_IM_FLAG_START = 1;
+ GTK_IM_FLAG_COMPOSITION = 2;
+ GTK_IM_FLAG_END = 4;
+ GTK_IM_FLAG_COMMIT = 8;
+ GTK_IM_FLAG_REPLACE = 16;
+
//-------------
//end of messages that are sent to the interface
//-------------