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