we need to use g_ signal_ Connect to associate key press event, key release event, and commit signals to process the input method.
g_ signal_ Connect
key press event
key release event
commit signals to process the input method
参考:
OSR模式和非OSR模式
OSR模式可以直接使用 SendEvent 发送中文字符
非OSR模式不能使用 SendEvent 发送中文字符,使用代替方案
实现原理:
ConnectKeyPressReleaseEvents 函数连接键盘事件和输入法事件信号
function GTKKeyPress(Widget: PGtkWidget; Event: PGdkEventKey; Data: gPointer): GBoolean; cdecl;
var
TempCefEvent: TCefKeyEvent;
EventString: PChar; // GTK1 and GTK2 workaround
pr: TGdkRectangle;
begin
pr.Height := 0;
pr.Width := 0;
pr.x := 0;
pr.y := 0;
//
EventString := nil;
gtk_im_context_focus_in(im_context);//设置焦点---重点
gtk_im_context_set_cursor_location(im_context, @pr);//设置光标--重点
gdk_event_key_get_string(Event, EventString); //取输入的字符
//
TempCefEvent.windows_key_code := GdkEventToWindowsKeyCode(Event);
TempCefEvent.native_key_code := Event^.hardware_keycode;
TempCefEvent.modifiers := Event^.state;
TempCefEvent.character := EventString^;
WriteLn('GTKKeyPress ', string(EventString), ' ', (Event^.state));
if (Event^._type = GDK_KEY_PRESS) then
begin
TempCefEvent.kind := KEYEVENT_RAWKEYDOWN;
MiniBrowserFrm.Chromium1.SendKeyEvent(@TempCefEvent);
TempCefEvent.kind := KEYEVENT_CHAR;
MiniBrowserFrm.Chromium1.SendKeyEvent(@TempCefEvent);
end
else
begin
TempCefEvent.kind := KEYEVENT_KEYUP;
MiniBrowserFrm.Chromium1.SendKeyEvent(@TempCefEvent);
end;
Result := True;
end;
procedure OnCommit(context: PGtkIMContext; const str: PChar); cdecl;
var
i: integer;
TempCefEvent: TCefKeyEvent;
ime: WideString;
begin
ime := WideString(string(str));
WriteLn('OnCommit ', ime, ' ', length(ime), ' IsComp: ', IsComp);
if IsComp then
begin
IsComp := false;
for i := 1 to length(ime) do
begin
WriteLn(' ime[', i, '] ', ime[i]);
TempCefEvent.is_system_key := 0;
TempCefEvent.modifiers := EVENTFLAG_NONE;
TempCefEvent.native_key_code := 25105;
TempCefEvent.windows_key_code := 25105;
//TempCefEvent.character := widechar(ime[i]);
//TempCefEvent.unmodified_character := widechar(ime[i]);
TempCefEvent.kind := KEYEVENT_RAWKEYDOWN;
MiniBrowserFrm.Chromium1.SendKeyEvent(@TempCefEvent);
TempCefEvent.kind := KEYEVENT_CHAR;
MiniBrowserFrm.Chromium1.SendKeyEvent(@TempCefEvent);
TempCefEvent.kind := KEYEVENT_KEYUP;
MiniBrowserFrm.Chromium1.SendKeyEvent(@TempCefEvent);
end;
end;
end;
procedure OnPreeditChanged(context: PGtkIMContext; aWidget: PGtkWidget); cdecl;
var
str: Pgchar;
attrs: PPangoAttrList;
cursor_pos: gint;
begin
str := nil;
attrs := nil;
gtk_im_context_get_preedit_string(context, @str, attrs, @cursor_pos);
WriteLn('OnPreeditChanged ', string(str));
if (str <> nil) and (string(str) <> '') then
begin
g_Free(str);
IsComp := True;
end
else
IsComp := False;
end;
procedure ConnectKeyPressReleaseEvents(const aWidget: PGtkWidget);
begin
g_signal_connect(aWidget, 'key-press-event', TGTKSignalFunc(@GTKKeyPress), nil);
g_signal_connect(aWidget, 'key-release-event', TGTKSignalFunc(@GTKKeyPress), nil);
// 连接 commit 信号
g_signal_connect(im_context, 'commit', TGTKSignalFunc(@OnCommit), nil);
// 连接 preedit-changed 信号
g_signal_connect(im_context, 'preedit-changed', TGTKSignalFunc(@OnPreeditChanged), nil);
end;