From b8129cf8ad8652cc3b946a9bb32418e39d42cf89 Mon Sep 17 00:00:00 2001 From: DistroBaker Date: Fri, 22 Jan 2021 01:35:25 +0000 Subject: [PATCH] Merged update from upstream sources This is an automated DistroBaker update from upstream sources. If you do not know what this is about or would like to opt out, contact the OSCI team. Source: https://src.fedoraproject.org/rpms/ibus.git#823ed8c386d7d06fc9f38a7bfac78ce1a377c04a --- ibus-HEAD.patch | 1465 +++++++++++++++++++++++++++++++++++++++++++++++ ibus.spec | 58 +- 2 files changed, 1516 insertions(+), 7 deletions(-) diff --git a/ibus-HEAD.patch b/ibus-HEAD.patch index 0b66c2d..5e3aadf 100644 --- a/ibus-HEAD.patch +++ b/ibus-HEAD.patch @@ -421,3 +421,1468 @@ index 06370a27..798ad04d 100644 -- 2.24.1 +From 5322c447c74a10ee54b482d6eff6da6d16a7c9ce Mon Sep 17 00:00:00 2001 +From: fujiwarat +Date: Sat, 21 Nov 2020 07:41:23 +0900 +Subject: [PATCH] ui/gtk3: Warn deprecated IBus XKB engines /w dialog + +simple.xml is updated by IBus release and some XKB engines +could be deprecated with xkeyboard-config updates. +Now a warning dialog is launched when the deprecated engines are +changed to xkb:us::eng engine. + +BUG=https://github.com/ibus/ibus/issues/2274 +--- + ui/gtk3/panel.vala | 15 +++++++++++++++ + 1 files changed, 33 insertions(+), 10 deletions(-) + +diff --git a/ui/gtk3/panel.vala b/ui/gtk3/panel.vala +index 627e26ae..01f87e33 100644 +--- a/ui/gtk3/panel.vala ++++ b/ui/gtk3/panel.vala +@@ -970,6 +970,21 @@ class Panel : IBus.PanelService { + names = {"xkb:us::eng"}; + m_settings_general.set_strv("preload-engines", names); + engines = m_bus.get_engines_by_names(names); ++ var message = _("Your input method %s does not exist in IBus " + ++ "input methods so \"US\" layout was configured instead " + ++ "of your input method. Please run `ibus-setup` command, " + ++ "open \"Input Method\" tab, and configure your input " + ++ "methods again.").printf(names[0]); ++ var dialog = new Gtk.MessageDialog( ++ null, ++ Gtk.DialogFlags.DESTROY_WITH_PARENT, ++ Gtk.MessageType.WARNING, ++ Gtk.ButtonsType.CLOSE, ++ message); ++ dialog.response.connect((id) => { ++ dialog.destroy(); ++ }); ++ dialog.show(); + } + + if (m_engines.length == 0) { +-- +2.28.0 + +From aec2ac75ea673d3701904735378765476cad0f21 Mon Sep 17 00:00:00 2001 +From: Gunnar Hjalmarsson +Date: Fri, 11 Dec 2020 16:27:36 +0900 +Subject: [PATCH] ui/gtk3: Warning dialog for any deprecated IBus XKB + engine + +This is a follow-up of commit 5322c447. That commit introduced +a warning dialog in case of an empty engines list. + +This commit makes a differently worded warning dialog be shown +in cases where the engines list is not empty but preload-engines +includes at least one deprecated engine. It also fixes a variable +confusion so a deprecated engine is mentioned in the first kind +of warning dialog and not the US engine. + +BUG=https://github.com/ibus/ibus/issues/2274 +--- + ui/gtk3/panel.vala | 30 +++++++++++++++++++----------- + 1 files changed, 43 insertions(+), 24 deletions(-) + +diff --git a/ui/gtk3/panel.vala b/ui/gtk3/panel.vala +index 01f87e33..ab2005d7 100644 +--- a/ui/gtk3/panel.vala ++++ b/ui/gtk3/panel.vala +@@ -966,25 +966,33 @@ class Panel : IBus.PanelService { + /* Fedora internal patch could save engines not in simple.xml + * likes 'xkb:cn::chi'. + */ +- if (engines.length == 0) { +- names = {"xkb:us::eng"}; +- m_settings_general.set_strv("preload-engines", names); +- engines = m_bus.get_engines_by_names(names); +- var message = _("Your input method %s does not exist in IBus " + +- "input methods so \"US\" layout was configured instead " + +- "of your input method. Please run `ibus-setup` command, " + +- "open \"Input Method\" tab, and configure your input " + +- "methods again.").printf(names[0]); ++ if (engines.length < names.length) { ++ string message1; ++ if (engines.length == 0) { ++ string[] fallback_names = {"xkb:us::eng"}; ++ m_settings_general.set_strv("preload-engines", fallback_names); ++ engines = m_bus.get_engines_by_names(fallback_names); ++ message1 = _("Your configured input method %s does not exist " + ++ "in IBus input methods so \"US\" layout was " + ++ "configured instead of your input method." ++ ).printf(names[0]); ++ } else { ++ message1 = _("At least one of your configured input methods " + ++ "does not exist in IBus input methods."); ++ } ++ var message2 = _("Please run `ibus-setup` command, open \"Input " + ++ "Method\" tab, and configure your input methods " + ++ "again."); + var dialog = new Gtk.MessageDialog( + null, + Gtk.DialogFlags.DESTROY_WITH_PARENT, + Gtk.MessageType.WARNING, + Gtk.ButtonsType.CLOSE, +- message); ++ "%s %s", message1, message2); + dialog.response.connect((id) => { + dialog.destroy(); + }); +- dialog.show(); ++ dialog.show_all(); + } + + if (m_engines.length == 0) { +-- +2.28.0 + +From 5d68b00e0464d43ba2f77697f9dcfbff78d7b438 Mon Sep 17 00:00:00 2001 +From: fujiwarat +Date: Thu, 31 Dec 2020 17:28:45 +0900 +Subject: [PATCH] engine: Fix iso-path in gensimple.py + +Replace datarootdir with ISOCODES_PREFIX. +--- + engine/Makefile.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/engine/Makefile.am b/engine/Makefile.am +index d810704b..1944c02b 100644 +--- a/engine/Makefile.am ++++ b/engine/Makefile.am +@@ -104,7 +104,7 @@ simple.xml.in: + --output=$@ \ + --version=$(VERSION).`date '+%Y%m%d'` \ + --exec-path=@libexecdir\@/ibus-engine-simple \ +- --iso-path=$(datarootdir)/xml/iso-codes/iso_639.xml \ ++ --iso-path=$(ISOCODES_PREFIX)/share/xml/iso-codes/iso_639.xml \ + --first-language \ + $(NULL) + +-- +2.28.0 + +From 29959e1d2521781c544879b284e03812a2a11b2e Mon Sep 17 00:00:00 2001 +From: fujiwarat +Date: Thu, 31 Dec 2020 20:00:02 +0900 +Subject: [PATCH] engine: Fix input in gensimple.py + +Replace datarootdir with XKBCONFIG_BASE. +--- + configure.ac | 7 +++++++ + engine/Makefile.am | 2 +- + 2 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 5753057b..9ed5cb66 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -720,6 +720,13 @@ PKG_CHECK_MODULES(ISOCODES, [ + ISOCODES_PREFIX=`$PKG_CONFIG iso-codes --variable=prefix` + AC_SUBST(ISOCODES_PREFIX) + ++PKG_CHECK_MODULES(XKBCONFIG, ++ [xkeyboard-config], ++ [XKBCONFIG_BASE=`$PKG_CONFIG xkeyboard-config --variable=xkb_base`], ++ [XKBCONFIG_BASE='$(datarootdir)/X11/xkb'] ++) ++AC_SUBST(XKBCONFIG_BASE) ++ + AC_SUBST([GDBUS_CODEGEN], [`$PKG_CONFIG --variable gdbus_codegen gio-2.0`]) + + # OUTPUT files +diff --git a/engine/Makefile.am b/engine/Makefile.am +index 1944c02b..84bc7f6c 100644 +--- a/engine/Makefile.am ++++ b/engine/Makefile.am +@@ -100,7 +100,7 @@ simple.xml: simple.xml.in + + simple.xml.in: + $(srcdir)/gensimple.py \ +- --input=$(datarootdir)/X11/xkb/rules/evdev.xml \ ++ --input=$(XKBCONFIG_BASE)/rules/evdev.xml \ + --output=$@ \ + --version=$(VERSION).`date '+%Y%m%d'` \ + --exec-path=@libexecdir\@/ibus-engine-simple \ +-- +2.28.0 + +From c7928b158741282e17a042f767bc5ae32c302c96 Mon Sep 17 00:00:00 2001 +From: fujiwarat +Date: Fri, 8 Jan 2021 18:45:55 +0900 +Subject: [PATCH] Add GTK4 IM module + +BUG=https://github.com/ibus/ibus/issues/2291 +--- + client/Makefile.am | 7 +- + client/gtk2/ibusimcontext.c | 352 +++++++++++++++++++++++++++++++----- + client/gtk4/Makefile.am | 66 +++++++ + client/gtk4/ibusim.c | 52 ++++++ + client/gtk4/ibusimcontext.c | 1 + + client/gtk4/ibusimcontext.h | 1 + + configure.ac | 32 ++++ + 7 files changed, 465 insertions(+), 46 deletions(-) + create mode 100644 client/gtk4/Makefile.am + create mode 100644 client/gtk4/ibusim.c + create mode 120000 client/gtk4/ibusimcontext.c + create mode 120000 client/gtk4/ibusimcontext.h + +diff --git a/client/Makefile.am b/client/Makefile.am +index 546ca132..1744518c 100644 +--- a/client/Makefile.am ++++ b/client/Makefile.am +@@ -3,7 +3,7 @@ + # ibus - The Input Bus + # + # Copyright (c) 2007-2010 Peng Huang +-# Copyright (c) 2007-2010 Red Hat, Inc. ++# Copyright (c) 2007-2020 Red Hat, Inc. + # + # This library is free software; you can redistribute it and/or + # modify it under the terms of the GNU Lesser General Public +@@ -28,6 +28,10 @@ if ENABLE_GTK3 + GTK3 = gtk3 + endif + ++if ENABLE_GTK4 ++GTK4 = gtk4 ++endif ++ + if ENABLE_XIM + X11 = x11 + endif +@@ -39,6 +43,7 @@ endif + SUBDIRS = \ + $(GTK2) \ + $(GTK3) \ ++ $(GTK4) \ + $(X11) \ + $(WAYLAND) \ + $(NULL) +diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c +index 50290c55..a23fc2e3 100644 +--- a/client/gtk2/ibusimcontext.c ++++ b/client/gtk2/ibusimcontext.c +@@ -2,8 +2,8 @@ + /* vim:set et sts=4: */ + /* ibus - The Input Bus + * Copyright (C) 2008-2013 Peng Huang +- * Copyright (C) 2015-2019 Takao Fujiwara +- * Copyright (C) 2008-2019 Red Hat, Inc. ++ * Copyright (C) 2015-2020 Takao Fujiwara ++ * Copyright (C) 2008-2020 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -32,8 +32,12 @@ + #include "ibusimcontext.h" + + #ifdef GDK_WINDOWING_WAYLAND ++#if GTK_CHECK_VERSION (3, 98, 4) ++#include ++#else + #include + #endif ++#endif + + #if !GTK_CHECK_VERSION (2, 91, 0) + # define DEPRECATED_GDK_KEYSYMS 1 +@@ -52,7 +56,11 @@ struct _IBusIMContext { + + /* instance members */ + GtkIMContext *slave; ++#if GTK_CHECK_VERSION (3, 98, 4) ++ GtkWidget *client_window; ++#else + GdkWindow *client_window; ++#endif + + IBusInputContext *ibuscontext; + +@@ -73,7 +81,12 @@ struct _IBusIMContext { + GCancellable *cancellable; + GQueue *events_queue; + +-#if !GTK_CHECK_VERSION (3, 93, 0) ++#if GTK_CHECK_VERSION (3, 98, 4) ++ GdkSurface *surface; ++ GdkDevice *device; ++ double x; ++ double y; ++#else + gboolean use_button_press_event; + #endif + }; +@@ -90,9 +103,11 @@ static guint _signal_preedit_end_id = 0; + static guint _signal_delete_surrounding_id = 0; + static guint _signal_retrieve_surrounding_id = 0; + ++#if !GTK_CHECK_VERSION (3, 98, 4) + static const gchar *_no_snooper_apps = NO_SNOOPER_APPS; + static gboolean _use_key_snooper = ENABLE_SNOOPER; + static guint _key_snooper_id = 0; ++#endif + + static gboolean _use_sync_mode = FALSE; + +@@ -101,8 +116,10 @@ static gboolean _use_discard_password = FALSE; + + static GtkIMContext *_focus_im_context = NULL; + static IBusInputContext *_fake_context = NULL; ++#if !GTK_CHECK_VERSION (3, 98, 4) + static GdkWindow *_input_window = NULL; + static GtkWidget *_input_widget = NULL; ++#endif + + /* functions prototype */ + static void ibus_im_context_class_init (IBusIMContextClass *class); +@@ -114,7 +131,11 @@ static void ibus_im_context_finalize (GObject *obj); + static void ibus_im_context_reset (GtkIMContext *context); + static gboolean ibus_im_context_filter_keypress + (GtkIMContext *context, ++#if GTK_CHECK_VERSION (3, 98, 4) ++ GdkEvent *key); ++#else + GdkEventKey *key); ++#endif + static void ibus_im_context_focus_in (GtkIMContext *context); + static void ibus_im_context_focus_out (GtkIMContext *context); + static void ibus_im_context_get_preedit_string +@@ -122,9 +143,15 @@ static void ibus_im_context_get_preedit_string + gchar **str, + PangoAttrList **attrs, + gint *cursor_pos); ++#if GTK_CHECK_VERSION (3, 98, 4) ++static void ibus_im_context_set_client_widget ++ (GtkIMContext *context, ++ GtkWidget *client); ++#else + static void ibus_im_context_set_client_window + (GtkIMContext *context, + GdkWindow *client); ++#endif + static void ibus_im_context_set_cursor_location + (GtkIMContext *context, + GdkRectangle *area); +@@ -239,6 +266,7 @@ ibus_im_context_new (void) + return IBUS_IM_CONTEXT (obj); + } + ++#if !GTK_CHECK_VERSION (3, 98, 4) + static gboolean + _focus_in_cb (GtkWidget *widget, + GdkEventFocus *event, +@@ -260,22 +288,41 @@ _focus_out_cb (GtkWidget *widget, + } + return FALSE; + } ++#endif /* end of GTK_CHECK_VERSION (3, 98, 4) */ + + static gboolean + ibus_im_context_commit_event (IBusIMContext *ibusimcontext, ++#if GTK_CHECK_VERSION (3, 98, 4) ++ GdkEvent *event) ++#else + GdkEventKey *event) ++#endif + { ++ guint keyval = 0; ++ GdkModifierType state = 0; + int i; + GdkModifierType no_text_input_mask; + gunichar ch; + ++#if GTK_CHECK_VERSION (3, 98, 4) ++ if (gdk_event_get_event_type (event) == GDK_KEY_RELEASE) ++ return FALSE; ++ keyval = gdk_key_event_get_keyval (event); ++ state = gdk_event_get_modifier_state (event); ++#else + if (event->type == GDK_KEY_RELEASE) + return FALSE; ++ keyval = event->keyval; ++ state = event->state; ++#endif ++ + /* Ignore modifier key presses */ + for (i = 0; i < G_N_ELEMENTS (IBUS_COMPOSE_IGNORE_KEYLIST); i++) +- if (event->keyval == IBUS_COMPOSE_IGNORE_KEYLIST[i]) ++ if (keyval == IBUS_COMPOSE_IGNORE_KEYLIST[i]) + return FALSE; +-#if GTK_CHECK_VERSION (3, 4, 0) ++#if GTK_CHECK_VERSION (3, 98, 4) ++ no_text_input_mask = GDK_MODIFIER_MASK; ++#elif GTK_CHECK_VERSION (3, 4, 0) + no_text_input_mask = gdk_keymap_get_modifier_mask ( + gdk_keymap_get_for_display (gdk_display_get_default ()), + GDK_MODIFIER_INTENT_NO_TEXT_INPUT); +@@ -290,13 +337,13 @@ ibus_im_context_commit_event (IBusIMContext *ibusimcontext, + + # undef _IBUS_NO_TEXT_INPUT_MOD_MASK + #endif +- if (event->state & no_text_input_mask || +- event->keyval == GDK_KEY_Return || +- event->keyval == GDK_KEY_ISO_Enter || +- event->keyval == GDK_KEY_KP_Enter) { ++ if (state & no_text_input_mask || ++ keyval == GDK_KEY_Return || ++ keyval == GDK_KEY_ISO_Enter || ++ keyval == GDK_KEY_KP_Enter) { + return FALSE; + } +- ch = ibus_keyval_to_unicode (event->keyval); ++ ch = ibus_keyval_to_unicode (keyval); + if (ch != 0 && !g_unichar_iscntrl (ch)) { + IBusText *text = ibus_text_new_from_unichar (ch); + g_signal_emit (ibusimcontext, _signal_commit_id, 0, text->text); +@@ -307,14 +354,26 @@ ibus_im_context_commit_event (IBusIMContext *ibusimcontext, + return FALSE; + } + ++struct _ProcessKeyEventData { ++ GdkEvent *event; ++ IBusIMContext *ibusimcontext; ++}; ++ ++typedef struct _ProcessKeyEventData ProcessKeyEventData; ++ + static void + _process_key_event_done (GObject *object, + GAsyncResult *res, + gpointer user_data) + { + IBusInputContext *context = (IBusInputContext *)object; +- GdkEventKey *event = (GdkEventKey *) user_data; ++ ++ ProcessKeyEventData *data = (ProcessKeyEventData *)user_data; ++ GdkEvent *event = data->event; ++ IBusIMContext *ibusimcontext = data->ibusimcontext; + GError *error = NULL; ++ ++ g_slice_free (ProcessKeyEventData, data); + gboolean retval = ibus_input_context_process_key_event_async_finish ( + context, + res, +@@ -326,46 +385,96 @@ _process_key_event_done (GObject *object, + } + + if (retval == FALSE) { +- event->state |= IBUS_IGNORED_MASK; +- gdk_event_put ((GdkEvent *)event); ++#if GTK_CHECK_VERSION (3, 98, 4) ++ g_return_if_fail (GTK_IS_IM_CONTEXT (ibusimcontext)); ++ gtk_im_context_filter_key ( ++ GTK_IM_CONTEXT (ibusimcontext), ++ gdk_event_get_event_type (event) == GDK_KEY_PRESS, ++ gdk_event_get_surface (event), ++ gdk_event_get_device (event), ++ gdk_event_get_time (event), ++ gdk_key_event_get_keycode (event), ++ gdk_event_get_modifier_state (event) | IBUS_IGNORED_MASK, ++ 0); ++#else ++ ((GdkEventKey *)event)->state |= IBUS_IGNORED_MASK; ++ gdk_event_put (event); ++#endif + } +- gdk_event_free ((GdkEvent *)event); ++#if GTK_CHECK_VERSION (3, 98, 4) ++ gdk_event_unref (event); ++#else ++ gdk_event_free (event); ++#endif + } + + static gboolean + _process_key_event (IBusInputContext *context, +- GdkEventKey *event) ++#if GTK_CHECK_VERSION (3, 98, 4) ++ GdkEvent *event, ++#else ++ GdkEventKey *event, ++#endif ++ IBusIMContext *ibusimcontext) + { +- guint state = event->state; ++ guint state; ++ guint keyval = 0; ++ guint16 hardware_keycode = 0; ++ guint keycode = 0; + gboolean retval = FALSE; + +- if (event->type == GDK_KEY_RELEASE) { ++#if GTK_CHECK_VERSION (3, 98, 4) ++ GdkModifierType gdkstate = gdk_event_get_modifier_state (event); ++ state = (uint)gdkstate; ++ if (gdk_event_get_event_type (event) == GDK_KEY_RELEASE) + state |= IBUS_RELEASE_MASK; +- } ++ keyval = gdk_key_event_get_keyval (event); ++ hardware_keycode = gdk_key_event_get_keycode (event); ++#else ++ state = event->state; ++ if (event->type == GDK_KEY_RELEASE) ++ state |= IBUS_RELEASE_MASK; ++ keyval = event->keyval; ++ hardware_keycode = event->hardware_keycode; ++#endif ++ keycode = hardware_keycode; + + if (_use_sync_mode) { + retval = ibus_input_context_process_key_event (context, +- event->keyval, +- event->hardware_keycode - 8, ++ keyval, ++ keycode - 8, + state); + } + else { ++ ProcessKeyEventData *data = g_slice_new0 (ProcessKeyEventData); ++#if GTK_CHECK_VERSION (3, 98, 4) ++ data->event = gdk_event_ref (event); ++#else ++ data->event = gdk_event_copy ((GdkEvent *)event); ++#endif ++ data->ibusimcontext = ibusimcontext; + ibus_input_context_process_key_event_async (context, +- event->keyval, +- event->hardware_keycode - 8, ++ keyval, ++ keycode - 8, + state, + -1, + NULL, + _process_key_event_done, +- gdk_event_copy ((GdkEvent *) event)); ++ data); + + retval = TRUE; + } + ++ /* GTK4 does not provide gtk_key_snooper_install() and also ++ * GtkIMContextClass->filter_keypress() cannot send the updated ++ * GdkEventKey so event->state is not updated here in GTK4. ++ */ ++#if !GTK_CHECK_VERSION (3, 98, 4) + if (retval) + event->state |= IBUS_HANDLED_MASK; + else + event->state |= IBUS_IGNORED_MASK; ++#endif + + return retval; + } +@@ -425,6 +534,7 @@ _set_content_type (IBusIMContext *context) + } + + ++#if !GTK_CHECK_VERSION (3, 98, 4) + static gint + _key_snooper_cb (GtkWidget *widget, + GdkEventKey *event, +@@ -526,7 +636,7 @@ _key_snooper_cb (GtkWidget *widget, + ibusimcontext->time = event->time; + } + +- retval = _process_key_event (ibuscontext, event); ++ retval = _process_key_event (ibuscontext, event, ibusimcontext); + + if (ibusimcontext != NULL) { + /* unref ibusimcontext could call ibus_im_context_finalize here +@@ -537,6 +647,7 @@ _key_snooper_cb (GtkWidget *widget, + + return retval; + } ++#endif + + static gboolean + _get_boolean_env(const gchar *name, +@@ -599,7 +710,11 @@ ibus_im_context_class_init (IBusIMContextClass *class) + im_context_class->focus_out = ibus_im_context_focus_out; + im_context_class->filter_keypress = ibus_im_context_filter_keypress; + im_context_class->get_preedit_string = ibus_im_context_get_preedit_string; ++#if GTK_CHECK_VERSION (3, 98, 4) ++ im_context_class->set_client_widget = ibus_im_context_set_client_widget; ++#else + im_context_class->set_client_window = ibus_im_context_set_client_window; ++#endif + im_context_class->set_cursor_location = ibus_im_context_set_cursor_location; + im_context_class->set_use_preedit = ibus_im_context_set_use_preedit; + im_context_class->set_surrounding = ibus_im_context_set_surrounding; +@@ -630,8 +745,10 @@ ibus_im_context_class_init (IBusIMContextClass *class) + g_signal_lookup ("retrieve-surrounding", G_TYPE_FROM_CLASS (class)); + g_assert (_signal_retrieve_surrounding_id != 0); + ++#if !GTK_CHECK_VERSION (3, 98, 4) + _use_key_snooper = !_get_boolean_env ("IBUS_DISABLE_SNOOPER", + !(ENABLE_SNOOPER)); ++#endif + _use_sync_mode = _get_boolean_env ("IBUS_ENABLE_SYNC_MODE", FALSE); + _use_discard_password = _get_boolean_env ("IBUS_DISCARD_PASSWORD", FALSE); + +@@ -656,6 +773,7 @@ ibus_im_context_class_init (IBusIMContextClass *class) + g_strfreev (apps); \ + } + ++#if !GTK_CHECK_VERSION (3, 98, 4) + /* env IBUS_DISABLE_SNOOPER does not exist */ + if (_use_key_snooper) { + /* disable snooper if app is in _no_snooper_apps */ +@@ -664,6 +782,7 @@ ibus_im_context_class_init (IBusIMContextClass *class) + _no_snooper_apps, + FALSE); + } ++#endif + if (!_use_discard_password) { + CHECK_APP_IN_CSV_ENV_VARIABLES (_use_discard_password, + IBUS_DISCARD_PASSWORD_APPS, +@@ -686,6 +805,7 @@ ibus_im_context_class_init (IBusIMContextClass *class) + } + + ++#if !GTK_CHECK_VERSION (3, 98, 4) + /* always install snooper */ + if (_key_snooper_id == 0) { + #pragma GCC diagnostic push +@@ -693,6 +813,7 @@ ibus_im_context_class_init (IBusIMContextClass *class) + _key_snooper_id = gtk_key_snooper_install (_key_snooper_cb, NULL); + #pragma GCC diagnostic pop + } ++#endif + + _daemon_name_watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION, + ibus_bus_get_service_name (_bus), +@@ -706,6 +827,7 @@ ibus_im_context_class_init (IBusIMContextClass *class) + static void + ibus_im_context_class_fini (IBusIMContextClass *class) + { ++#if !GTK_CHECK_VERSION (3, 98, 4) + if (_key_snooper_id != 0) { + IDEBUG ("snooper is terminated."); + #pragma GCC diagnostic push +@@ -714,6 +836,7 @@ ibus_im_context_class_fini (IBusIMContextClass *class) + #pragma GCC diagnostic pop + _key_snooper_id = 0; + } ++#endif + + g_bus_unwatch_name (_daemon_name_watch_id); + } +@@ -849,7 +972,11 @@ ibus_im_context_finalize (GObject *obj) + ibus_proxy_destroy ((IBusProxy *)ibusimcontext->ibuscontext); + } + ++#if GTK_CHECK_VERSION (3, 98, 4) ++ ibus_im_context_set_client_widget ((GtkIMContext *)ibusimcontext, NULL); ++#else + ibus_im_context_set_client_window ((GtkIMContext *)ibusimcontext, NULL); ++#endif + + if (ibusimcontext->slave) { + g_object_unref (ibusimcontext->slave); +@@ -864,8 +991,13 @@ ibus_im_context_finalize (GObject *obj) + pango_attr_list_unref (ibusimcontext->preedit_attrs); + } + ++#if GTK_CHECK_VERSION (3, 98, 4) ++ g_queue_free_full (ibusimcontext->events_queue, ++ (GDestroyNotify)gdk_event_unref); ++#else + g_queue_free_full (ibusimcontext->events_queue, + (GDestroyNotify)gdk_event_free); ++#endif + + G_OBJECT_CLASS(parent_class)->finalize (obj); + } +@@ -902,7 +1034,11 @@ ibus_im_context_clear_preedit_text (IBusIMContext *ibusimcontext) + + static gboolean + ibus_im_context_filter_keypress (GtkIMContext *context, ++#if GTK_CHECK_VERSION (3, 98, 4) ++ GdkEvent *event) ++#else + GdkEventKey *event) ++#endif + { + IDEBUG ("%s", __FUNCTION__); + +@@ -917,6 +1053,15 @@ ibus_im_context_filter_keypress (GtkIMContext *context, + if (!ibusimcontext->has_focus) + return gtk_im_context_filter_keypress (ibusimcontext->slave, event); + ++#if GTK_CHECK_VERSION (3, 98, 4) ++ { ++ GdkModifierType state = gdk_event_get_modifier_state (event); ++ if (state & IBUS_HANDLED_MASK) ++ return TRUE; ++ if (state & IBUS_IGNORED_MASK) ++ return ibus_im_context_commit_event (ibusimcontext, event); ++ } ++#else + if (event->state & IBUS_HANDLED_MASK) + return TRUE; + +@@ -931,17 +1076,28 @@ ibus_im_context_filter_keypress (GtkIMContext *context, + if (ibusimcontext->client_window == NULL && event->window != NULL) + gtk_im_context_set_client_window ((GtkIMContext *)ibusimcontext, + event->window); ++#endif + + _request_surrounding_text (ibusimcontext); + ++#if GTK_CHECK_VERSION (3, 98, 4) ++ ibusimcontext->time = gdk_event_get_time (event); ++ ibusimcontext->surface= gdk_event_get_surface (event); ++ ibusimcontext->device = gdk_event_get_device (event); ++ gdk_event_get_position (event, &ibusimcontext->x, &ibusimcontext->y); ++#else + ibusimcontext->time = event->time; ++#endif + + if (ibusimcontext->ibuscontext) { +- if (_process_key_event (ibusimcontext->ibuscontext, event)) ++ if (_process_key_event (ibusimcontext->ibuscontext, ++ event, ++ ibusimcontext)) { + return TRUE; +- else ++ } else { + return gtk_im_context_filter_keypress (ibusimcontext->slave, + event); ++ } + } + + /* At this point we _should_ be waiting for the IBus context to be +@@ -952,12 +1108,21 @@ ibus_im_context_filter_keypress (GtkIMContext *context, + ibus_bus_is_connected (_bus) == FALSE, + FALSE); + g_queue_push_tail (ibusimcontext->events_queue, ++#if GTK_CHECK_VERSION (3, 98, 4) ++ gdk_event_ref (event)); ++#else + gdk_event_copy ((GdkEvent *)event)); ++#endif + + if (g_queue_get_length (ibusimcontext->events_queue) > MAX_QUEUED_EVENTS) { + g_warning ("Events queue growing too big, will start to drop."); ++#if GTK_CHECK_VERSION (3, 98, 4) ++ gdk_event_unref ((GdkEvent *) ++ g_queue_pop_head (ibusimcontext->events_queue)); ++#else + gdk_event_free ((GdkEvent *) + g_queue_pop_head (ibusimcontext->events_queue)); ++#endif + } + + return TRUE; +@@ -966,26 +1131,29 @@ ibus_im_context_filter_keypress (GtkIMContext *context, + static void + ibus_im_context_focus_in (GtkIMContext *context) + { +- IDEBUG ("%s", __FUNCTION__); +- + IBusIMContext *ibusimcontext = (IBusIMContext *) context; ++ GtkWidget *widget = NULL; ++ ++ IDEBUG ("%s", __FUNCTION__); + + if (ibusimcontext->has_focus) + return; + + /* don't set focus on password entry */ ++#if GTK_CHECK_VERSION (3, 98, 4) ++ widget = ibusimcontext->client_window; ++#else + if (ibusimcontext->client_window != NULL) { +- GtkWidget *widget; +- + gdk_window_get_user_data (ibusimcontext->client_window, + (gpointer *)&widget); + +- if (GTK_IS_ENTRY (widget) && +- !gtk_entry_get_visibility (GTK_ENTRY (widget))) { +- return; +- } + } ++#endif + ++ if (widget && GTK_IS_ENTRY (widget) && ++ !gtk_entry_get_visibility (GTK_ENTRY (widget))) { ++ return; ++ } + /* Do not call gtk_im_context_focus_out() here. + * google-chrome's notification popup window (Pushbullet) + * takes the focus and the popup window disappears. +@@ -1014,10 +1182,10 @@ ibus_im_context_focus_in (GtkIMContext *context) + + /* set_cursor_location_internal() will get origin from X server, + * it blocks UI. So delay it to idle callback. */ +- gdk_threads_add_idle_full (G_PRIORITY_DEFAULT_IDLE, +- (GSourceFunc) _set_cursor_location_internal, +- g_object_ref (ibusimcontext), +- (GDestroyNotify) g_object_unref); ++ g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, ++ (GSourceFunc) _set_cursor_location_internal, ++ g_object_ref (ibusimcontext), ++ (GDestroyNotify) g_object_unref); + + /* retrieve the initial surrounding-text (regardless of whether + * the current IBus engine needs surrounding-text) */ +@@ -1122,7 +1290,7 @@ ibus_im_context_get_preedit_string (GtkIMContext *context, + } + + +-#if !GTK_CHECK_VERSION (3, 93, 0) ++#if !GTK_CHECK_VERSION (3, 98, 4) + /* Use the button-press-event signal until GtkIMContext always emits the reset + * signal. + * https://gitlab.gnome.org/GNOME/gtk/merge_requests/460 +@@ -1171,8 +1339,15 @@ _connect_button_press_event (IBusIMContext *ibusimcontext, + } + #endif + ++#if GTK_CHECK_VERSION (3, 98, 4) + static void +-ibus_im_context_set_client_window (GtkIMContext *context, GdkWindow *client) ++ibus_im_context_set_client_widget (GtkIMContext *context, ++ GtkWidget *client) ++#else ++static void ++ibus_im_context_set_client_window (GtkIMContext *context, ++ GdkWindow *client) ++#endif + { + IBusIMContext *ibusimcontext; + +@@ -1181,7 +1356,7 @@ ibus_im_context_set_client_window (GtkIMContext *context, GdkWindow *client) + ibusimcontext = IBUS_IM_CONTEXT (context); + + if (ibusimcontext->client_window) { +-#if !GTK_CHECK_VERSION (3, 93, 0) ++#if !GTK_CHECK_VERSION (3, 98, 4) + if (ibusimcontext->use_button_press_event) + _connect_button_press_event (ibusimcontext, FALSE); + #endif +@@ -1191,26 +1366,41 @@ ibus_im_context_set_client_window (GtkIMContext *context, GdkWindow *client) + + if (client != NULL) { + ibusimcontext->client_window = g_object_ref (client); +-#if !GTK_CHECK_VERSION (3, 93, 0) ++#if !GTK_CHECK_VERSION (3, 98, 4) + if (!ibusimcontext->use_button_press_event) + _connect_button_press_event (ibusimcontext, TRUE); + #endif + } ++#if GTK_CHECK_VERSION (3, 98, 4) ++ if (ibusimcontext->slave) ++ gtk_im_context_set_client_widget (ibusimcontext->slave, client); ++#else + if (ibusimcontext->slave) + gtk_im_context_set_client_window (ibusimcontext->slave, client); ++#endif + } + + static void + _set_rect_scale_factor_with_window (GdkRectangle *area, ++#if GTK_CHECK_VERSION (3, 98, 4) ++ GtkWidget *window) ++#else + GdkWindow *window) ++#endif + { + #if GTK_CHECK_VERSION (3, 10, 0) + int scale_factor; + + g_assert (area); ++#if GTK_CHECK_VERSION (3, 98, 4) ++ g_assert (GTK_IS_WIDGET (window)); ++ ++ scale_factor = gtk_widget_get_scale_factor (window); ++#else + g_assert (GDK_IS_WINDOW (window)); + + scale_factor = gdk_window_get_scale_factor (window); ++#endif + area->x *= scale_factor; + area->y *= scale_factor; + area->width *= scale_factor; +@@ -1230,6 +1420,7 @@ _set_cursor_location_internal (IBusIMContext *ibusimcontext) + + area = ibusimcontext->cursor_area; + ++#if !GTK_CHECK_VERSION (3, 98, 4) + #ifdef GDK_WINDOWING_WAYLAND + if (GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ())) { + gdouble px, py; +@@ -1253,10 +1444,14 @@ _set_cursor_location_internal (IBusIMContext *ibusimcontext) + area.height); + return FALSE; + } ++#endif + #endif + + if (area.x == -1 && area.y == -1 && area.width == 0 && area.height == 0) { +-#if GTK_CHECK_VERSION (2, 91, 0) ++#if GTK_CHECK_VERSION (3, 98, 4) ++ area.x = 0; ++ area.y += gtk_widget_get_height (ibusimcontext->client_window); ++#elif GTK_CHECK_VERSION (2, 91, 0) + area.x = 0; + area.y += gdk_window_get_height (ibusimcontext->client_window); + #else +@@ -1267,9 +1462,39 @@ _set_cursor_location_internal (IBusIMContext *ibusimcontext) + #endif + } + ++#if GTK_CHECK_VERSION (3, 93, 0) ++ { ++#if GTK_CHECK_VERSION (3, 98, 4) ++ GtkNative *native = gtk_widget_get_native ( ++ ibusimcontext->client_window); ++ GtkRoot *root = gtk_widget_get_root (ibusimcontext->client_window); ++ double nx, ny; ++ double px, py; ++ gtk_native_get_surface_transform (native, &nx, &ny); ++ px = (double)area.x + ibusimcontext->x - nx; ++ py = (double)area.y + ibusimcontext->y - ny; ++ gtk_widget_translate_coordinates (ibusimcontext->client_window, ++ (GtkWidget *)root, ++ px, py, ++ &px, &py); ++ area.x = (int)px; ++ area.y = (int)py; ++#else ++ GtkNative *native = gtk_widget_get_native ( ++ ibusimcontext->client_window); ++ GdkSurface *surface = gtk_native_get_surface (native); ++ int root_x = 0; ++ int root_y = 0; ++ gdk_surface_get_position (surface, &root_x, &root_y); ++ area.x += root_x; ++ area.y += root_y; ++#endif ++ } ++#else + gdk_window_get_root_coords (ibusimcontext->client_window, + area.x, area.y, + &area.x, &area.y); ++#endif + _set_rect_scale_factor_with_window (&area, ibusimcontext->client_window); + ibus_input_context_set_cursor_location (ibusimcontext->ibuscontext, + area.x, +@@ -1326,7 +1551,11 @@ get_selection_anchor_point (IBusIMContext *ibusimcontext, + if (ibusimcontext->client_window == NULL) { + return cursor_pos; + } ++#if GTK_CHECK_VERSION (3, 98, 4) ++ widget = ibusimcontext->client_window; ++#else + gdk_window_get_user_data (ibusimcontext->client_window, (gpointer *)&widget); ++#endif + + if (!GTK_IS_TEXT_VIEW (widget)){ + return cursor_pos; +@@ -1440,6 +1669,7 @@ _ibus_context_commit_text_cb (IBusInputContext *ibuscontext, + _request_surrounding_text (ibusimcontext); + } + ++#if !GTK_CHECK_VERSION (3, 98, 4) + static gboolean + _key_is_modifier (guint keyval) + { +@@ -1615,6 +1845,7 @@ _create_gdk_event (IBusIMContext *ibusimcontext, + out: + return event; + } ++#endif + + static void + _ibus_context_forward_key_event_cb (IBusInputContext *ibuscontext, +@@ -1624,9 +1855,32 @@ _ibus_context_forward_key_event_cb (IBusInputContext *ibuscontext, + IBusIMContext *ibusimcontext) + { + IDEBUG ("%s", __FUNCTION__); ++#if GTK_CHECK_VERSION (3, 98, 4) ++ int group = 0; ++ g_return_if_fail (GTK_IS_IM_CONTEXT (ibusimcontext)); ++ if (keycode == 0 && ibusimcontext->client_window) { ++ GdkDisplay *display = gtk_widget_get_display (ibusimcontext->client_window); ++ GdkKeymapKey *keys = NULL; ++ gint n_keys = 0; ++ if (!gdk_display_map_keyval (display, keyval, &keys, &n_keys)) ++ g_warning ("Failed to parse keycode from keyval %x", keyval); ++ keycode = keys->keycode; ++ group = keys->group; ++ } ++ gtk_im_context_filter_key ( ++ GTK_IM_CONTEXT (ibusimcontext), ++ (state & IBUS_RELEASE_MASK) ? FALSE : TRUE, ++ ibusimcontext->surface, ++ ibusimcontext->device, ++ ibusimcontext->time, ++ keycode, ++ (GdkModifierType)state, ++ group); ++#else + GdkEventKey *event = _create_gdk_event (ibusimcontext, keyval, keycode, state); + gdk_event_put ((GdkEvent *)event); + gdk_event_free ((GdkEvent *)event); ++#endif + } + + static void +@@ -1660,7 +1914,7 @@ _ibus_context_update_preedit_text_cb (IBusInputContext *ibuscontext, + ibusimcontext->preedit_attrs = NULL; + } + +-#if !GTK_CHECK_VERSION (3, 93, 0) ++#if !GTK_CHECK_VERSION (3, 98, 4) + if (!ibusimcontext->use_button_press_event && + mode == IBUS_ENGINE_PREEDIT_COMMIT) { + if (ibusimcontext->client_window) { +@@ -1847,10 +2101,18 @@ _create_input_context_done (IBusBus *bus, + } + + if (!g_queue_is_empty (ibusimcontext->events_queue)) { ++#if GTK_CHECK_VERSION (3, 98, 4) ++ GdkEvent *event; ++#else + GdkEventKey *event; ++#endif + while ((event = g_queue_pop_head (ibusimcontext->events_queue))) { +- _process_key_event (context, event); ++ _process_key_event (context, event, ibusimcontext); ++#if GTK_CHECK_VERSION (3, 98, 4) ++ gdk_event_unref (event); ++#else + gdk_event_free ((GdkEvent *)event); ++#endif + } + } + } +diff --git a/client/gtk4/Makefile.am b/client/gtk4/Makefile.am +new file mode 100644 +index 00000000..8d8b31db +--- /dev/null ++++ b/client/gtk4/Makefile.am +@@ -0,0 +1,66 @@ ++# vim:set noet ts=4: ++# ++# ibus - The Input Bus ++# ++# Copyright (c) 2020 Takao Fujiwara ++# Copyright (c) 2020 Red Hat, Inc. ++# ++# This library is free software; you can redistribute it and/or ++# modify it under the terms of the GNU Lesser General Public ++# License as published by the Free Software Foundation; either ++# version 2.1 of the License, or (at your option) any later version. ++# ++# This library is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++# Lesser General Public License for more details. ++# ++# You should have received a copy of the GNU Lesser General Public ++# License along with this library; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 ++# USA ++ ++libibus = $(top_builddir)/src/libibus-@IBUS_API_VERSION@.la ++ ++AM_CPPFLAGS = \ ++ -I$(top_srcdir)/src \ ++ -I$(top_builddir)/src \ ++ $(NULL) ++ ++immoduledir = @GTK4_IM_MODULEDIR@ ++immodule_LTLIBRARIES = libim-ibus.la ++ ++libim_ibus_la_SOURCES = \ ++ ibusim.c \ ++ ibusimcontext.c \ ++ ibusimcontext.h \ ++ $(NULL) ++ ++libim_ibus_la_DEPENDENCIES = $(libibus) ++ ++libim_ibus_la_CFLAGS = \ ++ @GTK4_CFLAGS@ \ ++ @DBUS_CFLAGS@ \ ++ -DG_LOG_DOMAIN=\"IBUS\" \ ++ $(NULL) ++ ++libim_ibus_la_LIBADD = \ ++ @GTK4_LIBS@ \ ++ @DBUS_LIBS@ \ ++ $(libibus) \ ++ $(NULL) ++libim_ibus_la_LDFLAGS = \ ++ -avoid-version \ ++ -module \ ++ $(NULL) ++ ++$(libibus): ++ (cd $(top_builddir)/src; make ) ++ ++EXTRA_DIST = \ ++ $(NULL) ++ ++test: all ++ GTK_IM_MODULE=ibus gedit ++ ++-include $(top_srcdir)/git.mk +diff --git a/client/gtk4/ibusim.c b/client/gtk4/ibusim.c +new file mode 100644 +index 00000000..5ecf9778 +--- /dev/null ++++ b/client/gtk4/ibusim.c +@@ -0,0 +1,52 @@ ++/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ ++/* vim:set et ts=4: */ ++/* ibus - The Input Bus ++ * Copyright (C) 2008-2010 Peng Huang ++ * Copyright (C) 2020 Takao Fujiwara ++ * Copyright (C) 2008-2020 Red Hat, Inc. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 ++ * USA ++ */ ++ ++#include ++#include ++#include ++#include "ibusimcontext.h" ++ ++G_MODULE_EXPORT void ++g_io_im_ibus_load (GTypeModule *type_module) ++{ ++ static gboolean inited = FALSE; ++ ++ if (!inited) { ++ ibus_init (); ++ ibus_im_context_register_type (type_module); ++ g_io_extension_point_implement ("gtk-im-module", ++ IBUS_TYPE_IM_CONTEXT, ++ "ibus", ++ 50); ++ inited = TRUE; ++ } ++ /* make module resident */ ++ g_type_module_use (type_module); ++} ++ ++G_MODULE_EXPORT void ++g_io_im_ibus_unload (GTypeModule *type_module) ++{ ++ g_type_module_unuse (type_module); ++} ++ +diff --git a/client/gtk4/ibusimcontext.c b/client/gtk4/ibusimcontext.c +new file mode 120000 +index 00000000..41896f05 +--- /dev/null ++++ b/client/gtk4/ibusimcontext.c +@@ -0,0 +1 @@ ++../gtk2/ibusimcontext.c +\ No newline at end of file +diff --git a/client/gtk4/ibusimcontext.h b/client/gtk4/ibusimcontext.h +new file mode 120000 +index 00000000..29759883 +--- /dev/null ++++ b/client/gtk4/ibusimcontext.h +@@ -0,0 +1 @@ ++../gtk2/ibusimcontext.h +\ No newline at end of file +diff --git a/configure.ac b/configure.ac +index 9ed5cb66..ffea3317 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -193,6 +193,15 @@ AC_ARG_ENABLE(gtk3, + ) + AM_CONDITIONAL([ENABLE_GTK3], [test x"$enable_gtk3" = x"yes"]) + ++# --enable-gtk4 option. ++AC_ARG_ENABLE(gtk4, ++ AS_HELP_STRING([--enable-gtk4], ++ [Build gtk4 im module]), ++ [enable_gtk4=$enableval], ++ [enable_gtk4=no] ++) ++AM_CONDITIONAL([ENABLE_GTK4], [test x"$enable_gtk4" = x"yes"]) ++ + # --disable-xim option. + AC_ARG_ENABLE(xim, + AS_HELP_STRING([--disable-xim], +@@ -257,6 +266,18 @@ if test x"$enable_gdk3_wayland" != x"yes"; then + fi + AM_CONDITIONAL([ENABLE_GDK3_WAYLAND], [test x"$enable_gdk3_wayland" = x"yes"]) + ++if test x"$enable_gtk4" = x"yes"; then ++ # check for gtk4 ++ PKG_CHECK_MODULES(GTK4, [ ++ gtk4 ++ ]) ++ ++ gtk4_binary_version=`$PKG_CONFIG --variable=gtk_binary_version gtk4` ++ GTK4_IM_MODULEDIR="$libdir"/gtk-4.0/$gtk4_binary_version/immodules ++else ++ enable_gtk4="no (disabled, use --enable-gtk4 to enable)" ++fi ++ + if test x"$enable_xim" = x"yes"; then + # Check for x11 + PKG_CHECK_MODULES(X11, [ +@@ -478,6 +499,14 @@ AC_ARG_WITH(gtk3-im-module-dir, + ) + AC_SUBST(GTK3_IM_MODULEDIR) + ++# Define gtk4 immodule dir. ++AC_ARG_WITH(gtk4-im-module-dir, ++ AS_HELP_STRING([--with-gtk4-im-module-dir[=DIR]], ++ [Select gtk4 immodule dir]), ++ GTK4_IM_MODULEDIR=$with_gtk4_im_module_dir ++) ++AC_SUBST(GTK4_IM_MODULEDIR) ++ + if test x"$enable_python" = x"yes"; then + # Check for dbus-python. + AC_ARG_ENABLE(dbus-python-check, +@@ -737,6 +766,7 @@ ibus.spec + client/Makefile + client/gtk2/Makefile + client/gtk3/Makefile ++client/gtk4/Makefile + client/x11/Makefile + client/wayland/Makefile + src/Makefile +@@ -786,8 +816,10 @@ Build options: + Enable python2 $enable_python2 + Gtk2 immodule dir $GTK2_IM_MODULEDIR + Gtk3 immodule dir $GTK3_IM_MODULEDIR ++ Gtk4 immodule dir $GTK4_IM_MODULEDIR + Build gtk2 immodule $enable_gtk2 + Build gtk3 immodule $enable_gtk3 ++ Build gtk4 immodule $enable_gtk4 + Build XIM agent server $enable_xim + Build wayland support $enable_wayland + Build gdk3 wayland support $enable_gdk3_wayland +-- +2.28.0 + +From d0a47c3c82b1a0c263ff8b95f9cf5c0a5d1f228d Mon Sep 17 00:00:00 2001 +From: fujiwarat +Date: Fri, 8 Jan 2021 18:48:13 +0900 +Subject: [PATCH] client/gtk2: Add XTranslateCoordinates for GTK4 X11 + coordinate + +GdkWindow had the absolute coordiante in the private class in GTK3 +but the absolute coordiane no longer exists in GTK4 for Wayland. +Now get the toplevel window coordiante for the warkaround in GTK4 +but the coordiante of the inner widgets is no longer available too. + +BUG=https://gitlab.gnome.org/GNOME/gtk/-/issues/3024#note_987835 +--- + client/gtk2/ibusimcontext.c | 47 ++++++++++++++++++++++++------------- + 1 file changed, 31 insertions(+), 16 deletions(-) + +diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c +index a23fc2e3..e153081d 100644 +--- a/client/gtk2/ibusimcontext.c ++++ b/client/gtk2/ibusimcontext.c +@@ -39,6 +39,13 @@ + #endif + #endif + ++#ifdef GDK_WINDOWING_X11 ++#if GTK_CHECK_VERSION (3, 98, 4) ++#include ++#include ++#endif ++#endif ++ + #if !GTK_CHECK_VERSION (2, 91, 0) + # define DEPRECATED_GDK_KEYSYMS 1 + #endif +@@ -1462,24 +1469,33 @@ _set_cursor_location_internal (IBusIMContext *ibusimcontext) + #endif + } + +-#if GTK_CHECK_VERSION (3, 93, 0) +- { + #if GTK_CHECK_VERSION (3, 98, 4) ++#ifdef GDK_WINDOWING_X11 ++ GdkDisplay *display = gtk_widget_get_display (ibusimcontext->client_window); ++ if (GDK_IS_X11_DISPLAY (display)) { ++ Display *xdisplay = gdk_x11_display_get_xdisplay (display); ++ Window root_window = gdk_x11_display_get_xrootwindow (display); + GtkNative *native = gtk_widget_get_native ( + ibusimcontext->client_window); +- GtkRoot *root = gtk_widget_get_root (ibusimcontext->client_window); +- double nx, ny; +- double px, py; +- gtk_native_get_surface_transform (native, &nx, &ny); +- px = (double)area.x + ibusimcontext->x - nx; +- py = (double)area.y + ibusimcontext->y - ny; +- gtk_widget_translate_coordinates (ibusimcontext->client_window, +- (GtkWidget *)root, +- px, py, +- &px, &py); +- area.x = (int)px; +- area.y = (int)py; +-#else ++ GdkSurface *surface = gtk_native_get_surface (native); ++ /* The window is the toplevel window but not the inner text widget. ++ * Unfortunatelly GTK4 cannot get the coordinate of the text widget. ++ */ ++ Window window = gdk_x11_surface_get_xid (surface); ++ Window child; ++ int x, y; ++ XTranslateCoordinates (xdisplay, window, root_window, ++ 0, 0, &x, &y, &child); ++ XWindowAttributes xwa; ++ XGetWindowAttributes (xdisplay, window, &xwa); ++ area.x = x - xwa.x + area.x; ++ area.y = y - xwa.y + area.y; ++ area.width = xwa.width; ++ area.height = xwa.height; ++ } ++#endif ++#elif GTK_CHECK_VERSION (3, 93, 0) ++ { + GtkNative *native = gtk_widget_get_native ( + ibusimcontext->client_window); + GdkSurface *surface = gtk_native_get_surface (native); +@@ -1488,7 +1504,6 @@ _set_cursor_location_internal (IBusIMContext *ibusimcontext) + gdk_surface_get_position (surface, &root_x, &root_y); + area.x += root_x; + area.y += root_y; +-#endif + } + #else + gdk_window_get_root_coords (ibusimcontext->client_window, +-- +2.28.0 + +From ef4c5c7ef790ce1f80e94a5463e110ed4bae254e Mon Sep 17 00:00:00 2001 +From: fujiwarat +Date: Wed, 20 Jan 2021 17:26:47 +0900 +Subject: [PATCH] setup: Search engine name directly + +Currently users can search language names only in the language list +in ibus-setup. After a language is selected and open, engine names can +be searched. +Now engine names also can be searched in the language list. +--- + setup/enginedialog.py | 40 +++++++++++++++++++++------------------- + 1 file changed, 21 insertions(+), 19 deletions(-) + +diff --git a/setup/enginedialog.py b/setup/enginedialog.py +index 72deada8..e1c322bf 100644 +--- a/setup/enginedialog.py ++++ b/setup/enginedialog.py +@@ -4,7 +4,7 @@ + # ibus - The Input Bus + # + # Copyright (c) 2015 Peng Huang +-# Copyright (c) 2015-2019 Takao Fujiwara ++# Copyright (c) 2015-2021 Takao Fujiwara + # Copyright (c) 2013-2015 Red Hat, Inc. + # + # This program is free software; you can redistribute it and/or +@@ -112,15 +112,20 @@ class EngineDialog(Gtk.Dialog): + return False + if self.__filter_word == None: + return True ++ if row.back: ++ return True + +- name = row.name.lower() +- untrans = row.untrans.lower() +- if self.__filter_word != None: +- word = self.__filter_word.lower() +- if name.startswith(word): +- return True +- if untrans.startswith(word): +- return True ++ word = self.__filter_word.lower() ++ if word in row.name.lower(): ++ return True ++ if word in row.untrans.lower(): ++ return True ++ if row.lang_info and row.name in self.__engines_for_lang: ++ for row_e in self.__engines_for_lang[row.name]: ++ if word in row_e.name.lower(): ++ return True ++ if word in row_e.untrans.lower(): ++ return True + return False + + +@@ -129,11 +134,9 @@ class EngineDialog(Gtk.Dialog): + self.__show_more() + return + if row.back: +- self.__filter_entry.set_text('') + self.__show_lang_rows() + return + if row.lang_info: +- self.__filter_entry.set_text('') + self.__show_engines_for_lang(row) + return + +@@ -232,6 +235,7 @@ class EngineDialog(Gtk.Dialog): + description = i18n.gettext_engine_description(engine) + row = self.__list_box_row_new(longname) + row.untrans = engine.get_longname() ++ row.rank = engine.get_rank() + row.set_tooltip_text(description) + row.engine = engine + widget = self.__padded_label_new(longname, +@@ -260,16 +264,13 @@ class EngineDialog(Gtk.Dialog): + lang = row.name + + def cmp_engine(a, b): +- if a.get_rank() == b.get_rank(): +- a_longname = i18n.gettext_engine_longname(a) +- b_longname = i18n.gettext_engine_longname(b) +- return locale.strcoll(a_longname, b_longname) +- return int(b.get_rank() - a.get_rank()) ++ if a.rank == b.rank: ++ return locale.strcoll(a.name, b.name) ++ return int(b.rank - a.rank) + + self.__engines_for_lang[lang].sort( + key = functools.cmp_to_key(cmp_engine)) +- for e in self.__engines_for_lang[lang]: +- row = self.__engine_row_new(e) ++ for row in self.__engines_for_lang[lang]: + self.__list.add(row) + + +@@ -329,7 +330,8 @@ class EngineDialog(Gtk.Dialog): + if l not in self.__engines_for_lang: + self.__engines_for_lang[l] = [] + i18n.init_textdomain(e.get_textdomain()) +- self.__engines_for_lang[l].append(e) ++ row = self.__engine_row_new(e) ++ self.__engines_for_lang[l].append(row) + + # Retrieve Untranslated language names. + untrans = IBus.get_untranslated_language_name(e.get_language()) +-- +2.28.0 + diff --git a/ibus.spec b/ibus.spec index bdd1e65..b5f74f2 100644 --- a/ibus.spec +++ b/ibus.spec @@ -12,13 +12,25 @@ # for bytecompile in %%{_datadir}/ibus/setup %global __python %{__python3} +%if (0%{?fedora} > 33 || 0%{?rhel} > 8) +%bcond_without gtk4 +%else +%bcond_with gtk4 +%endif + %if %with_pkg_config %{!?gtk2_binary_version: %global gtk2_binary_version %(pkg-config --variable=gtk_binary_version gtk+-2.0)} %{!?gtk3_binary_version: %global gtk3_binary_version %(pkg-config --variable=gtk_binary_version gtk+-3.0)} +%if %{with gtk4} +%{!?gtk4_binary_version: %global gtk4_binary_version %(pkg-config --variable=gtk_binary_version gtk4)} +%else +%{!?gtk4_binary_version: %global gtk4_binary_version ?.?.?} +%endif %global glib_ver %([ -a %{_libdir}/pkgconfig/glib-2.0.pc ] && pkg-config --modversion glib-2.0 | cut -d. -f 1,2 || echo -n "999") %else %{!?gtk2_binary_version: %global gtk2_binary_version ?.?.?} %{!?gtk3_binary_version: %global gtk3_binary_version ?.?.?} +%{!?gtk4_binary_version: %global gtk4_binary_version ?.?.?} %global glib_ver 0 %endif @@ -26,7 +38,7 @@ Name: ibus Version: 1.5.23 -Release: 2%{?dist} +Release: 3%{?dist} Summary: Intelligent Input Bus for Linux OS License: LGPLv2+ URL: https://github.com/ibus/%name/wiki @@ -44,6 +56,9 @@ BuildRequires: libtool BuildRequires: glib2-doc BuildRequires: gtk2-devel BuildRequires: gtk3-devel +%if %{with gtk4} +BuildRequires: gtk4-devel +%endif BuildRequires: dbus-glib-devel BuildRequires: dbus-python-devel >= %{dbus_python_version} BuildRequires: desktop-file-utils @@ -103,12 +118,6 @@ Requires: %{_sbindir}/alternatives Requires(post): %{_sbindir}/alternatives Requires(postun): %{_sbindir}/alternatives -%if (0%{?fedora} > 29 || 0%{?rhel} > 8) -# Obsoletes ibus-xkbc by ibus xkb engine -Provides: ibus-xkbc = 1.3.4 -Obsoletes: ibus-xkbc < 1.3.4 -%endif - %global _xinputconf %{_sysconfdir}/X11/xinit/xinput.d/ibus.conf %description @@ -150,6 +159,17 @@ Requires(post): glib2 >= %{glib_ver} %description gtk3 This package contains IBus IM module for GTK3 +%if %{with gtk4} +%package gtk4 +Summary: IBus IM module for GTK4 +Requires: %{name}-libs%{?_isa} = %{version}-%{release} +Requires: glib2 >= %{glib_ver} +Requires(post): glib2 >= %{glib_ver} + +%description gtk4 +This package contains IBus IM module for GTK4 +%endif + %package setup Summary: IBus setup utility Requires: %{name} = %{version}-%{release} @@ -157,6 +177,7 @@ Requires: %{name} = %{version}-%{release} Requires: python3-gobject BuildRequires: gobject-introspection-devel BuildRequires: pygobject3-devel +BuildRequires: make BuildArch: noarch %description setup @@ -244,6 +265,8 @@ the functionality of the installed %{name} package. %autosetup -S git # cp client/gtk2/ibusimcontext.c client/gtk3/ibusimcontext.c || : # cp client/gtk2/ibusim.c client/gtk3/ibusim.c || : +# cp client/gtk2/ibusimcontext.c client/gtk4/ibusimcontext.c || : +cp client/gtk2/ibusimcontext.c client/gtk3/ibusimcontext.c || : # prep test @@ -255,6 +278,11 @@ do abort fi done +diff client/gtk2/ibusimcontext.c client/gtk4/ibusimcontext.c +if test $? -ne 0 ; then + echo "Have to copy ibusimcontext.c into client/gtk4" + abort +fi %build #autoreconf -f -i -v @@ -265,6 +293,9 @@ autoreconf -f -i -v --disable-static \ --enable-gtk2 \ --enable-gtk3 \ +%if %{with gtk4} + --enable-gtk4 \ +%endif --enable-xim \ --enable-gtk-doc \ --enable-surrounding-text \ @@ -287,6 +318,9 @@ make install DESTDIR=$RPM_BUILD_ROOT INSTALL='install -p' rm -f $RPM_BUILD_ROOT%{_libdir}/libibus-*%{ibus_api_version}.la rm -f $RPM_BUILD_ROOT%{_libdir}/gtk-2.0/%{gtk2_binary_version}/immodules/im-ibus.la rm -f $RPM_BUILD_ROOT%{_libdir}/gtk-3.0/%{gtk3_binary_version}/immodules/im-ibus.la +%if %{with gtk4} +rm -f $RPM_BUILD_ROOT%{_libdir}/gtk-4.0/%{gtk4_binary_version}/immodules/libim-ibus.la +%endif # install man page for S in %{SOURCE2} @@ -397,6 +431,11 @@ dconf update || : %files gtk3 %{_libdir}/gtk-3.0/%{gtk3_binary_version}/immodules/im-ibus.so +%if %{with gtk4} +%files gtk4 +%{_libdir}/gtk-4.0/%{gtk4_binary_version}/immodules/libim-ibus.so +%endif + # The setup package won't include icon files so that # gtk-update-icon-cache is executed in the main package only one time. %files setup @@ -451,6 +490,11 @@ dconf update || : %{_datadir}/installed-tests/ibus %changelog +* Wed Jan 20 2021 Takao Fujiwara - 1.5.23-3 +- Enable IM gtk4 module +- Fix to rename xkb:de::ger to sync xkeyboard-config +- Enhance ibus-setup search engine + * Fri Nov 20 2020 Takao Fujiwara - 1.5.23-2 - Bug 1898065 - Fix build failure of emoji-*.dict with CLDR 38 - Fix build failure with Vala 0.50