Control: tags 1003691 + patch
Control: tags 1003691 + pending

Dear maintainer,

I've prepared an NMU for scim (versioned as 1.4.18+git20211204-0.1) and
uploaded it to DELAYED/14. Please feel free to tell me if I
should delay it longer.

Regards.

diff -Nru scim-1.4.18/configure.ac scim-1.4.18+git20211204/configure.ac
--- scim-1.4.18/configure.ac    2017-07-30 22:45:36.000000000 -0400
+++ scim-1.4.18+git20211204/configure.ac        2021-12-04 05:40:01.000000000
-0500
@@ -242,6 +242,10 @@
                        [SCIM_HAS_GTK3=yes],
                        [SCIM_HAS_GTK3=no])
 
+PKG_CHECK_MODULES(GTK4, [gtk4 >= 4.0.0 pango >= 1.48.0 gdk-pixbuf-2.0 >=
2.42.0],
+                       [SCIM_HAS_GTK4=yes],
+                       [SCIM_HAS_GTK4=no])
+
 SCIM_HAS_GTK2_2=no
 if test "$SCIM_HAS_GTK2" = "yes"; then
   if $PKG_CONFIG --exists "gtk+-2.0 >= 2.2" ; then
@@ -261,6 +265,14 @@
   AC_SUBST(GTK3_IM_MODULEDIR)
 fi
 
+if test "$SCIM_HAS_GTK4" = "yes"; then
+  GTK4_VERSION=4.0.0
+  GTK4_BINARY_VERSION=`$PKG_CONFIG --variable=gtk_binary_version gtk4`
+  GTK4_LIBDIR=`$PKG_CONFIG --variable=libdir gtk4`
+  GTK4_IM_MODULEDIR=$GTK4_LIBDIR/gtk-4.0/$GTK4_BINARY_VERSION/immodules
+  AC_SUBST(GTK4_IM_MODULEDIR)
+fi
+
 # Check if we have gthread
 PKG_CHECK_MODULES(GTHREAD2,[gthread-2.0 >= 2.0.0],
                        [SCIM_HAS_GTHREAD2=yes],
@@ -344,6 +356,11 @@
            [Select GTK3 immodule dir])],
        [GTK3_IM_MODULEDIR=$with_gtk3_im_module_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_ARG_WITH([qt3-moc],
        [AS_HELP_STRING([--with-qt3-moc=file],
                [Select QT3 moc program (default to QT3_PREFIX/bin/moc)])],
@@ -483,6 +500,12 @@
        [],
        [enable_gtk3_immodule=yes])
 
+AC_ARG_ENABLE([gtk4-immodule],
+       [AS_HELP_STRING([--disable-gtk4-immodule],
+               [Do not build GTK4 IMModule])],
+       [],
+       [enable_gtk4_immodule=yes])
+
 AC_ARG_ENABLE([qt3-immodule],
        [AS_HELP_STRING([--disable-qt3-immodule],
                [Do not build QT3 IMModule])],
@@ -625,6 +648,15 @@
   enable_gtk3_immodule=no
 fi
 
+if test "$enable_gtk4_immodule" = "yes" -a "$SCIM_HAS_GTK4" = "yes"; then
+  SCIM_BUILD_GTK4_IMMODULE=1
+  SCIM_BUILD_IMMODULE=1
+  enable_immodule=yes
+else
+  SCIM_BUILD_GTK4_IMMODULE=0
+  enable_gtk4_immodule=no
+fi
+
 if test "$enable_im_agent" = "yes"; then
   SCIM_BUILD_IM_AGENT=1
 else
@@ -657,6 +689,17 @@
   enable_gtk3_immodule=no
 fi
 
+if test "$enable_gtk4_immodule" = "yes" -a "$SCIM_HAS_GTK4" = "yes"; then
+  SCIM_BUILD_GTK4_IMMODULE=1
+  SCIM_BUILD_IMMODULE=1
+  enable_immodule=yes
+  SCIM_BUILD_IM_AGENT=1
+  enable_im_agent=yes
+else
+  SCIM_BUILD_GTK4_IMMODULE=0
+  enable_gtk4_immodule=no
+fi
+
 if test "$enable_qt3_immodule" = "yes" -a "$SCIM_HAS_QT3" = "yes"; then
   SCIM_BUILD_QT3_IMMODULE=1
   SCIM_BUILD_IMMODULE=1
@@ -692,19 +735,37 @@
   enable_clutter_immodule=no
 fi
 
-if test "$SCIM_HAS_GTK3" = "yes" -a "$SCIM_HAS_GTK2" = "yes"; then
+if test "$SCIM_HAS_GTK4" = "yes" -a "$SCIM_HAS_GTK3" = "yes" -a
"$SCIM_HAS_GTK2" = "yes"; then
   if test "$WANT_GTK_VERSION" = "2"; then
        USE_GTK_VERSION="2"
-  else
+  elif test "$WANT_GTK_VERSION" = "3"; then
        USE_GTK_VERSION="3"
+  else
+       USE_GTK_VERSION="4"
   fi
+elif test "$SCIM_HAS_GTK4" = "yes"; then
+  USE_GTK_VERSION="4"
 elif test "$SCIM_HAS_GTK3" = "yes"; then
   USE_GTK_VERSION="3"
 elif test "$SCIM_HAS_GTK2" = "yes"; then
   USE_GTK_VERSION="2"
 fi
 
-if test "$USE_GTK_VERSION" = "3"; then
+if test "$USE_GTK_VERSION" = "4"; then
+  SCIM_HAS_GTK=yes
+  GTK_LIBDIR=$GTK4_LIBDIR
+  GTK_VERSION=$GTK4_VERSION
+  GTK_MAJOR_VERSION=4
+  GTK_BINARY_VERSION=$GTK4_BINARY_VERSION
+  GTK_CFLAGS=$GTK4_CFLAGS
+  GTK_LIBS=$GTK4_LIBS
+  AC_SUBST(GTK_LIBDIR)
+  AC_SUBST(GTK_VERSION)
+  AC_SUBST(GTK_MAJOR_VERSION)
+  AC_SUBST(GTK_BINARY_VERSION)
+  AC_SUBST(GTK_CFLAGS)
+  AC_SUBST(GTK_LIBS)
+elif test "$USE_GTK_VERSION" = "3"; then
   SCIM_HAS_GTK=yes
   GTK_LIBDIR=$GTK3_LIBDIR
   GTK_VERSION=$GTK3_VERSION
@@ -753,7 +814,7 @@
 fi
 
 enable_tray_icon=no
-if test \( "$SCIM_HAS_GTK3"="yes" -o "$SCIM_HAS_GTK2_2" = "yes" \) -a "$no_x"
!= "yes"; then
+if test \( "$SCIM_HAS_GTK4"="yes" -o "$SCIM_HAS_GTK3"="yes" -o
"$SCIM_HAS_GTK2_2" = "yes" \) -a "$no_x" != "yes"; then
   enable_tray_icon=yes
   AC_DEFINE(ENABLE_TRAY_ICON,1,[Enable the TrayIcon code.])
 fi
@@ -818,6 +879,9 @@
 AM_CONDITIONAL(SCIM_BUILD_GTK3_IMMODULE,
         [test "$enable_gtk3_immodule" = "yes"])
 
+AM_CONDITIONAL(SCIM_BUILD_GTK4_IMMODULE,
+        [test "$enable_gtk4_immodule" = "yes"])
+
 AM_CONDITIONAL(SCIM_BUILD_QT3_IMMODULE,
         [test "$enable_qt3_immodule" = "yes"])
 
@@ -868,6 +932,7 @@
 AC_SUBST(SCIM_BUILD_IM_AGENT)
 AC_SUBST(SCIM_BUILD_GTK2_IMMODULE)
 AC_SUBST(SCIM_BUILD_GTK3_IMMODULE)
+AC_SUBST(SCIM_BUILD_GTK4_IMMODULE)
 AC_SUBST(SCIM_BUILD_QT3_IMMODULE)
 AC_SUBST(SCIM_BUILD_QT4_IMMODULE)
 AC_SUBST(SCIM_BUILD_CLUTTER_IMMODULE)
@@ -930,8 +995,7 @@
                 extras/immodules/client-common/Makefile
                 extras/immodules/client-gtk/gtk2/Makefile
                 extras/immodules/client-gtk/gtk3/Makefile
-                extras/immodules/client-qt/qt3/Makefile
-                extras/immodules/client-qt/qt4/Makefile
+                extras/immodules/client-gtk/gtk4/Makefile
                 extras/immodules/client-clutter/Makefile
                 extras/immodules/doc/Makefile
                 tests/Makefile
@@ -978,6 +1042,7 @@
 
   GTK2 IMModule dir        $GTK2_IM_MODULEDIR
   GTK3 IMModule dir        $GTK3_IM_MODULEDIR
+  GTK4 IMModule dir        $GTK4_IM_MODULEDIR
   QT3 IMModule dir         $QT3_IM_MODULEDIR
   QT4 IMModule dir         $QT4_IM_MODULEDIR
   Clutter IMModule dir     $CLUTTER_IM_MODULEDIR
@@ -991,6 +1056,7 @@
   Scim IM Agent            $enable_im_agent
   GTK2 IMModule            $enable_gtk2_immodule
   GTK3 IMModule            $enable_gtk3_immodule
+  GTK4 IMModule            $enable_gtk4_immodule
   QT3 IMModule             $enable_qt3_immodule
   QT4 IMModule             $enable_qt4_immodule
   CLUTTER IMModule         $enable_clutter_immodule
diff -Nru scim-1.4.18/debian/changelog scim-
1.4.18+git20211204/debian/changelog
--- scim-1.4.18/debian/changelog        2019-12-28 18:45:08.000000000 -0500
+++ scim-1.4.18+git20211204/debian/changelog    2022-01-13 14:11:59.000000000
-0500
@@ -1,3 +1,15 @@
+scim (1.4.18+git20211204-0.1) unstable; urgency=medium
+
+  * Non-maintainer upload.
+  * New upstream git HEAD snapshot.
+  * debian/patches/03_scim_spelling_fixes.patch: Dropped, merged upstream.
+  * debian/control: Enable GTK4 immodule build. (Closes: #1003691)
+  * debian/rules: Use "dh_missing --fail-missing".
+  * debian/not-installed: Explicitly list files not installed.
+  * Move debian/TODO.Debian to debian/TODO (lintian).
+
+ -- Boyuan Yang <[email protected]>  Thu, 13 Jan 2022 14:11:59 -0500
+
 scim (1.4.18-2.2) unstable; urgency=medium
 
   * Non-maintainer upload. I took just one part of Tz-Hua's merge request
diff -Nru scim-1.4.18/debian/control scim-1.4.18+git20211204/debian/control
--- scim-1.4.18/debian/control  2019-12-28 18:17:20.000000000 -0500
+++ scim-1.4.18+git20211204/debian/control      2022-01-13 13:35:20.000000000
-0500
@@ -8,7 +8,8 @@
  dh-autoreconf, intltool, autopoint, pkg-config, x11proto-core-dev, libx11-
dev,
  libpango1.0-dev, libglib2.0-dev, libgtk2.0-dev, libgtk-3-dev | libgtk2.0-dev
(<< 2.21),
  libclutter-1.0-dev, libclutter-imcontext-0.1-dev,
- libltdl-dev, doxygen
+ libltdl-dev, doxygen,
+ libgtk-4-dev,
 Homepage: https://github.com/scim-im/scim
 Vcs-Browser: https://github.com/leggewie-DM/scim
 Vcs-Git: https://github.com/leggewie-DM/scim.git
diff -Nru scim-1.4.18/debian/not-installed scim-1.4.18+git20211204/debian/not-
installed
--- scim-1.4.18/debian/not-installed    1969-12-31 19:00:00.000000000 -0500
+++ scim-1.4.18+git20211204/debian/not-installed        2022-01-13
14:00:26.000000000 -0500
@@ -0,0 +1,7 @@
+usr/lib/*/clutter-imcontext/immodules/*.a
+usr/lib/*/clutter-imcontext/immodules/*.la
+usr/lib/*/gtk-*/*/immodules/*.a
+usr/lib/*/gtk-*/*/immodules/*.la
+usr/lib/*/scim-1.0/*/*/*.a
+usr/lib/*/scim-1.0/*/*/*.la
+usr/share/control-center-2.0/capplets/scim-setup.desktop
diff -Nru scim-1.4.18/debian/patches/03_scim_spelling_fixes.patch scim-
1.4.18+git20211204/debian/patches/03_scim_spelling_fixes.patch
--- scim-1.4.18/debian/patches/03_scim_spelling_fixes.patch     2018-06-19
09:11:07.000000000 -0400
+++ scim-1.4.18+git20211204/debian/patches/03_scim_spelling_fixes.patch 1969-
12-31 19:00:00.000000000 -0500
@@ -1,38 +0,0 @@
-Description: Fix some spelling errors in scim's source files.
-Forwarded: https://github.com/scim-im/scim/issues/25
-Author: Hugh McMaster <[email protected]>
-Last-Update: 2018-06-17
-
---- scim-1.4.18.orig/extras/immodules/agent/scim-bridge-agent.cpp
-+++ scim-1.4.18/extras/immodules/agent/scim-bridge-agent.cpp
-@@ -249,16 +249,16 @@ retval_t ScimBridgeAgentImpl::run_event_
-             } else {
-                 if (socket_fd > max_fd) max_fd = socket_fd;
-                 if (triggers & SCIM_BRIDGE_AGENT_EVENT_READ) {
--                    scim_bridge_pdebugln (1, "FD (%d) is registred as a
reading socket", socket_fd);
-+                    scim_bridge_pdebugln (1, "FD (%d) is registered as a
reading socket", socket_fd);
-                     FD_SET (socket_fd, &read_set);
-                 }
-                 if (triggers & SCIM_BRIDGE_AGENT_EVENT_WRITE) {
-                     FD_SET (socket_fd, &write_set);
--                    scim_bridge_pdebugln (1, "FD (%d) is registred as a
writing socket", socket_fd);
-+                    scim_bridge_pdebugln (1, "FD (%d) is registered as a
writing socket", socket_fd);
-                 }
-                 if (triggers & SCIM_BRIDGE_AGENT_EVENT_ERROR) {
-                     FD_SET (socket_fd, &error_set);
--                    scim_bridge_pdebugln (1, "FD (%d) is registred as a
error socket", socket_fd);
-+                    scim_bridge_pdebugln (1, "FD (%d) is registered as a
error socket", socket_fd);
-                 }
-             }
-             ++i;
---- scim-1.4.18.orig/extras/immodules/client-common/scim-bridge-client.c
-+++ scim-1.4.18/extras/immodules/client-common/scim-bridge-client.c
-@@ -1569,7 +1569,7 @@ retval_t scim_bridge_client_reset_imcont
-     }
- 
-     if (pending_response.status == RESPONSE_SUCCEEDED) {
--        scim_bridge_pdebugln (6, "reseted: id = %d", id);
-+        scim_bridge_pdebugln (6, "reset: id = %d", id);
-         pending_response.header = NULL;
-         pending_response.status = RESPONSE_DONE;
-         return RETVAL_SUCCEEDED;
diff -Nru scim-1.4.18/debian/patches/series scim-
1.4.18+git20211204/debian/patches/series
--- scim-1.4.18/debian/patches/series   2018-06-17 05:39:43.000000000 -0400
+++ scim-1.4.18+git20211204/debian/patches/series       2022-01-13
13:38:38.000000000 -0500
@@ -1,3 +1,2 @@
 01_scim_config.patch
 02_replace_AC_CHECK_FILE.patch
-03_scim_spelling_fixes.patch
diff -Nru scim-1.4.18/debian/rules scim-1.4.18+git20211204/debian/rules
--- scim-1.4.18/debian/rules    2019-12-28 18:24:36.000000000 -0500
+++ scim-1.4.18+git20211204/debian/rules        2022-01-13 13:51:58.000000000
-0500
@@ -35,3 +35,6 @@
 
 override_dh_shlibdeps:
        dh_shlibdeps -l debian/libscim8v5/usr/lib -L libscim8v5
+
+override_dh_missing:
+       dh_missing --fail-missing
diff -Nru scim-1.4.18/debian/scim-gtk-immodule.install scim-
1.4.18+git20211204/debian/scim-gtk-immodule.install
--- scim-1.4.18/debian/scim-gtk-immodule.install        2018-04-15
08:04:19.000000000 -0400
+++ scim-1.4.18+git20211204/debian/scim-gtk-immodule.install    2022-01-13
13:51:54.000000000 -0500
@@ -1 +1 @@
-usr/lib/*/gtk-?.0/*/immodules/im-scim.so
+usr/lib/*/gtk-?.0/*/immodules/*.so
diff -Nru scim-1.4.18/debian/TODO scim-1.4.18+git20211204/debian/TODO
--- scim-1.4.18/debian/TODO     1969-12-31 19:00:00.000000000 -0500
+++ scim-1.4.18+git20211204/debian/TODO 2022-01-13 13:30:42.000000000 -0500
@@ -0,0 +1,14 @@
+Short Term
+----------
+Add scim-setup.desktop handling in postinst and postrm.
+
+Use AM_MAINTAINER_MODE in configure.ac to avoid timestamp skews.
+
+
+Long Term
+---------
+Investigate "SONAME in dynamic loaded module" issue.
+ Solved? http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=323216
+
+
+
diff -Nru scim-1.4.18/debian/TODO.Debian scim-
1.4.18+git20211204/debian/TODO.Debian
--- scim-1.4.18/debian/TODO.Debian      2018-04-15 08:04:19.000000000 -0400
+++ scim-1.4.18+git20211204/debian/TODO.Debian  1969-12-31 19:00:00.000000000
-0500
@@ -1,14 +0,0 @@
-Short Term
-----------
-Add scim-setup.desktop handling in postinst and postrm.
-
-Use AM_MAINTAINER_MODE in configure.ac to avoid timestamp skews.
-
-
-Long Term
----------
-Investigate "SONAME in dynamic loaded module" issue.
- Solved? http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=323216
-
-
-
diff -Nru scim-1.4.18/extras/immodules/agent/scim-bridge-agent.cpp scim-
1.4.18+git20211204/extras/immodules/agent/scim-bridge-agent.cpp
--- scim-1.4.18/extras/immodules/agent/scim-bridge-agent.cpp    2017-07-30
22:45:36.000000000 -0400
+++ scim-1.4.18+git20211204/extras/immodules/agent/scim-bridge-
agent.cpp       2021-12-04 05:40:01.000000000 -0500
@@ -249,16 +249,16 @@
             } else {
                 if (socket_fd > max_fd) max_fd = socket_fd;
                 if (triggers & SCIM_BRIDGE_AGENT_EVENT_READ) {
-                    scim_bridge_pdebugln (1, "FD (%d) is registred as a
reading socket", socket_fd);
+                    scim_bridge_pdebugln (1, "FD (%d) is registered as a
reading socket", socket_fd);
                     FD_SET (socket_fd, &read_set);
                 }
                 if (triggers & SCIM_BRIDGE_AGENT_EVENT_WRITE) {
                     FD_SET (socket_fd, &write_set);
-                    scim_bridge_pdebugln (1, "FD (%d) is registred as a
writing socket", socket_fd);
+                    scim_bridge_pdebugln (1, "FD (%d) is registered as a
writing socket", socket_fd);
                 }
                 if (triggers & SCIM_BRIDGE_AGENT_EVENT_ERROR) {
                     FD_SET (socket_fd, &error_set);
-                    scim_bridge_pdebugln (1, "FD (%d) is registred as a error
socket", socket_fd);
+                    scim_bridge_pdebugln (1, "FD (%d) is registered as a
error socket", socket_fd);
                 }
             }
             ++i;
diff -Nru scim-1.4.18/extras/immodules/client-common/scim-bridge-client.c
scim-1.4.18+git20211204/extras/immodules/client-common/scim-bridge-client.c
--- scim-1.4.18/extras/immodules/client-common/scim-bridge-client.c     2017-
07-30 22:45:36.000000000 -0400
+++ scim-1.4.18+git20211204/extras/immodules/client-common/scim-bridge-
client.c        2021-12-04 05:40:01.000000000 -0500
@@ -1569,7 +1569,7 @@
     }
 
     if (pending_response.status == RESPONSE_SUCCEEDED) {
-        scim_bridge_pdebugln (6, "reseted: id = %d", id);
+        scim_bridge_pdebugln (6, "reset: id = %d", id);
         pending_response.header = NULL;
         pending_response.status = RESPONSE_DONE;
         return RETVAL_SUCCEEDED;
diff -Nru scim-1.4.18/extras/immodules/client-gtk/gtk2/Makefile.am scim-
1.4.18+git20211204/extras/immodules/client-gtk/gtk2/Makefile.am
--- scim-1.4.18/extras/immodules/client-gtk/gtk2/Makefile.am    2017-07-30
22:45:36.000000000 -0400
+++ scim-1.4.18+git20211204/extras/immodules/client-
gtk/gtk2/Makefile.am    2021-12-04 05:40:01.000000000 -0500
@@ -40,11 +40,12 @@
 
 im_scim_la_LDFLAGS = -rpath $(moduledir) \
                     -avoid-version -no-undefined \
-                    -module \
-                    @GTK2_LIBS@
+                    -module
 
 im_scim_la_LIBADD  =
$(top_builddir)/extras/immodules/common/libscimbridgecommon.la \
-
                                        
$(top_builddir)/extras/immodules/client-common/libscimbridgeclientcommon.la
+                    $(top_builddir)/extras/immodules/client-
common/libscimbridgeclientcommon.la \
+                    @X_LIBS@ \
+                    @GTK2_LIBS@
 
 endif
 
diff -Nru scim-1.4.18/extras/immodules/client-gtk/gtk3/Makefile.am scim-
1.4.18+git20211204/extras/immodules/client-gtk/gtk3/Makefile.am
--- scim-1.4.18/extras/immodules/client-gtk/gtk3/Makefile.am    2017-07-30
22:45:36.000000000 -0400
+++ scim-1.4.18+git20211204/extras/immodules/client-
gtk/gtk3/Makefile.am    2021-12-04 05:40:01.000000000 -0500
@@ -40,11 +40,12 @@
 
 im_scim_la_LDFLAGS = -rpath $(moduledir) \
                     -avoid-version -no-undefined \
-                    -module \
-                    @GTK3_LIBS@
+                    -module
 
 im_scim_la_LIBADD  =
$(top_builddir)/extras/immodules/common/libscimbridgecommon.la \
-
                                        
$(top_builddir)/extras/immodules/client-common/libscimbridgeclientcommon.la
+                    $(top_builddir)/extras/immodules/client-
common/libscimbridgeclientcommon.la \
+                    @X_LIBS@ \
+                    @GTK3_LIBS@
 
 endif
 
diff -Nru scim-1.4.18/extras/immodules/client-gtk/gtk4/im-scim-bridge-gtk.c
scim-1.4.18+git20211204/extras/immodules/client-gtk/gtk4/im-scim-bridge-gtk.c
--- scim-1.4.18/extras/immodules/client-gtk/gtk4/im-scim-bridge-gtk.c   1969-
12-31 19:00:00.000000000 -0500
+++ scim-1.4.18+git20211204/extras/immodules/client-gtk/gtk4/im-scim-bridge-
gtk.c   2021-12-04 05:40:01.000000000 -0500
@@ -0,0 +1,61 @@
+/*
+ * SCIM Bridge
+ *
+ * Copyright (c) 2006 Ryo Dairiki <[email protected]>
+ *
+ *
+ * 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 and 
+ * appearing in the file LICENSE.LGPL included in the package of this file.
+ * You can also redistribute it and/or modify it under the terms of 
+ * the GNU General Public License as published by the Free Software
Foundation and 
+ * appearing in the file LICENSE.GPL included in the package of this file.
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <gtk/gtkimmodule.h>
+
+#include "scim-bridge.h"
+#include "scim-bridge-client.h"
+#include "../scim-bridge-client-gtk.h"
+#include "scim-bridge-client-imcontext-gtk.h"
+
+/* Implementations */
+void g_io_im_scim_load (GIOModule *io_module)
+{
+    static boolean initialized = FALSE;
+
+    if (initialized) {
+        return;
+    }
+
+    scim_bridge_client_imcontext_register_type (io_module);
+    GIOExtension *ext = g_io_extension_point_implement (
+        GTK_IM_MODULE_EXTENSION_POINT_NAME,
+        GTK_TYPE_SCIM_CLIENT_IMCONTEXT,
+        "scim",
+        100);
+    scim_bridge_client_gtk_initialize ();
+
+    atexit (scim_bridge_client_gtk_finalize);
+
+    g_type_module_use(G_TYPE_MODULE(io_module));
+
+    initialized = TRUE;
+}
+
+
+void g_io_im_scim_unload (GIOModule *io_module)
+{
+    g_type_module_unuse(G_TYPE_MODULE(io_module));
+    scim_bridge_client_gtk_finalize ();
+}
diff -Nru scim-1.4.18/extras/immodules/client-gtk/gtk4/Makefile.am scim-
1.4.18+git20211204/extras/immodules/client-gtk/gtk4/Makefile.am
--- scim-1.4.18/extras/immodules/client-gtk/gtk4/Makefile.am    1969-12-31
19:00:00.000000000 -0500
+++ scim-1.4.18+git20211204/extras/immodules/client-
gtk/gtk4/Makefile.am    2021-12-04 05:40:01.000000000 -0500
@@ -0,0 +1,52 @@
+## Makefile.am -- Process this file with automake to produce Makefile.in
+##
+## Copyright (C) 2006 Ryo Dairiki
+##
+##
+## 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 and 
+## appearing in the file LICENSE.LGPL included in the package of this file.
+## You can also redistribute it and/or modify it under the terms of 
+## the GNU General Public License as published by the Free Software
Foundation and 
+## appearing in the file LICENSE.GPL included in the package of this file.
+##
+## 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.
+
+if SCIM_BUILD_GTK4_IMMODULE
+
+AM_CPPFLAGS    = -I$(top_builddir) \
+                 -I$(top_srcdir) \
+                         -I$(top_srcdir)/extras/immodules/common \
+                         -I$(top_srcdir)/extras/immodules/client-common
+
+noinst_HEADERS = ../scim-bridge-client-gtk.h \
+                                ../scim-bridge-client-imcontext-gtk.h \
+                                ../scim-bridge-client-key-event-utility-
gtk.h
+
+moduledir = @GTK4_IM_MODULEDIR@
+
+module_LTLIBRARIES = libim-scim.la
+
+libim_scim_la_SOURCES = im-scim-bridge-gtk.c \
+                                               ../scim-bridge-client-gtk.c \
+                                               scim-bridge-client-imcontext-
gtk.c \
+                                               scim-bridge-client-key-event-
utility-gtk.c
+
+libim_scim_la_CXXFLAGS=@GTK4_CFLAGS@
+libim_scim_la_CFLAGS  =@GTK4_CFLAGS@
+
+libim_scim_la_LDFLAGS = -rpath $(moduledir) \
+                    -avoid-version -no-undefined \
+                    -module
+
+libim_scim_la_LIBADD  =
$(top_builddir)/extras/immodules/common/libscimbridgecommon.la \
+                    $(top_builddir)/extras/immodules/client-
common/libscimbridgeclientcommon.la \
+                    @GTK4_LIBS@ \
+                    @X_LIBS@
+
+endif
+
+MAINTAINERCLEANFILES   = Makefile.in
diff -Nru scim-1.4.18/extras/immodules/client-gtk/gtk4/scim-bridge-client-
imcontext-gtk.c scim-1.4.18+git20211204/extras/immodules/client-gtk/gtk4/scim-
bridge-client-imcontext-gtk.c
--- scim-1.4.18/extras/immodules/client-gtk/gtk4/scim-bridge-client-imcontext-
gtk.c   1969-12-31 19:00:00.000000000 -0500
+++ scim-1.4.18+git20211204/extras/immodules/client-gtk/gtk4/scim-bridge-
client-imcontext-gtk.c  2021-12-04 05:40:01.000000000 -0500
@@ -0,0 +1,997 @@
+/*
+ * SCIM Bridge
+ *
+ * Copyright (c) 2006 Ryo Dairiki <[email protected]>
+ *
+ *
+ * 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 and 
+ * appearing in the file LICENSE.LGPL included in the package of this file.
+ * You can also redistribute it and/or modify it under the terms of 
+ * the GNU General Public License as published by the Free Software
Foundation and 
+ * appearing in the file LICENSE.GPL included in the package of this file.
+ *
+ * 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.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <gtk/gtk.h>
+
+#include <gdk/gdk.h>
+
+#ifdef GDK_WINDOWING_X11 
+#include <gdk/x11/gdkx.h>
+#include <X11/Xlib.h>
+#endif
+
+#include "scim-bridge-attribute.h"
+#include "scim-bridge-client.h"
+#include "scim-bridge-client-imcontext-gtk.h"
+#include "scim-bridge-client-key-event-utility-gtk.h"
+#include "scim-bridge-imcontext.h"
+#include "scim-bridge-messenger.h"
+#include "scim-bridge-output.h"
+#include "scim-bridge-string.h"
+
+/* Typedef */
+struct _ScimBridgeClientIMContext
+{
+    GtkIMContext parent;
+    GtkIMContext *slave;
+    boolean slave_preedit;
+
+    scim_bridge_imcontext_id_t id;
+
+    char *preedit_string;
+    size_t preedit_string_capacity;
+    
+    PangoAttrList *preedit_attributes;
+
+    unsigned int preedit_cursor_position;
+    boolean preedit_cursor_flicking;
+    
+    boolean preedit_shown;
+    boolean preedit_started;
+
+    char *commit_string;
+    size_t commit_string_capacity;
+    
+    boolean enabled;
+
+    GtkWidget *client_widget;
+
+    int cursor_x;
+    int cursor_y;
+    int window_x;
+    int window_y;
+};
+
+
+typedef struct {
+    guint16 red;
+    guint16 green;
+    guint16 blue;
+} Color;
+
+
+/* Private variables */
+static Color preedit_normal_background;
+static Color preedit_normal_foreground;
+static Color preedit_active_background;
+static Color preedit_active_foreground;
+
+static GType class_type = 0;
+static GObjectClass *root_klass = NULL;
+
+static ScimBridgeClientIMContext *focused_imcontext = NULL;
+static GtkWidget *focused_widget = NULL;
+
+/* Class functions */
+static void scim_bridge_client_imcontext_class_initialize
(ScimBridgeClientIMContextClass *klass, gpointer *klass_data);
+
+static void scim_bridge_client_imcontext_initialize
(ScimBridgeClientIMContext *context, ScimBridgeClientIMContextClass *klass);
+static void scim_bridge_client_imcontext_finalize (GObject *object);
+
+static gboolean scim_bridge_client_imcontext_filter_key_event (GtkIMContext
*context, GdkEvent *event);
+static void scim_bridge_client_imcontext_reset (GtkIMContext *context);
+static void scim_bridge_client_imcontext_get_preedit_string (GtkIMContext
*context, gchar **str, PangoAttrList **attrs, gint *cursor_pos);
+static void scim_bridge_client_imcontext_set_preedit_enabled (GtkIMContext
*context, gboolean enabled);
+
+static void scim_bridge_client_imcontext_set_client_widget (GtkIMContext
*context, GtkWidget *window);
+static void scim_bridge_client_imcontext_focus_in (GtkIMContext *context);
+static void scim_bridge_client_imcontext_focus_out (GtkIMContext *context);
+static void scim_bridge_client_imcontext_set_cursor_location (GtkIMContext
*context, GdkRectangle *area);
+
+/* slave callbacks */
+static void gtk_im_slave_commit_cb (GtkIMContext *context, const char *str,
ScimBridgeClientIMContext *imcontext);
+static void gtk_im_slave_preedit_changed_cb (GtkIMContext *context,
ScimBridgeClientIMContext *imcontext);
+static void gtk_im_slave_preedit_start_cb (GtkIMContext *context,
ScimBridgeClientIMContext *imcontext);
+static void gtk_im_slave_preedit_end_cb (GtkIMContext *context,
ScimBridgeClientIMContext *imcontext);
+
+static retval_t filter_key_event (ScimBridgeClientIMContext *imcontext,
GdkEvent *event, boolean *consumed)
+{
+    scim_bridge_pdebugln (5, "filter_key_event ()");
+    
+    if (focused_imcontext != imcontext)
+        scim_bridge_client_imcontext_focus_in (GTK_IM_CONTEXT (imcontext));
+    //focused_widget = gtk_get_event_widget (event);
+    focused_widget = imcontext->client_widget;
+    
+    if (scim_bridge_client_is_messenger_opened ()) {
+        ScimBridgeKeyEvent *bridge_key_event = scim_bridge_alloc_key_event
();
+        scim_bridge_key_event_gdk_to_bridge (bridge_key_event, imcontext-
>client_widget, event);
+
+        *consumed = FALSE;
+        const retval_t retval_error = scim_bridge_client_handle_key_event
(imcontext, bridge_key_event, consumed);
+        scim_bridge_free_key_event (bridge_key_event);
+
+        if (retval_error) {
+            scim_bridge_perrorln ("An IOException at filter_key_event ()");
+        } else {
+            return RETVAL_SUCCEEDED;
+        }
+    }
+
+    return RETVAL_FAILED;
+}
+
+
+static retval_t set_cursor_location (ScimBridgeClientIMContext *imcontext,
int window_x, int window_y, int cursor_x, int cursor_y)
+{
+    scim_bridge_pdebugln (5, "set_cursor_location ()");
+
+    if (imcontext->window_x == window_x && imcontext->window_y == window_y &&
imcontext->cursor_x == cursor_x && imcontext->cursor_y == cursor_y) {
+        return RETVAL_SUCCEEDED;
+    } else {
+        imcontext->cursor_x = cursor_x;
+        imcontext->cursor_y = cursor_y;
+        imcontext->window_x = window_x;
+        imcontext->window_y = window_y;
+
+        scim_bridge_pdebugln (3, "The cursor location is changed: x = %d +
%d\ty = %d + %d", imcontext->window_x, imcontext->cursor_x, imcontext-
>window_y, imcontext->cursor_y);
+
+        if (scim_bridge_client_is_messenger_opened ()) {
+            if (scim_bridge_client_set_cursor_location (imcontext, imcontext-
>window_x + imcontext->cursor_x, imcontext->window_y + imcontext->cursor_y)) {
+                scim_bridge_perrorln ("An IOException occurred at
set_cursor_location ()");
+                return RETVAL_FAILED;
+            } else {
+                return RETVAL_SUCCEEDED;
+            }
+        }
+    }
+
+    return RETVAL_FAILED;
+}
+
+
+static void widget_get_origin(GtkWidget *widget, int *x, int *y)
+{
+    double widget_x, widget_y;
+    GtkRoot *root = gtk_widget_get_root(widget);
+    gtk_widget_translate_coordinates(widget, GTK_WIDGET(root), 0, 0,
&widget_x, &widget_y);
+
+    GdkSurface *surface = gtk_native_get_surface (GTK_NATIVE(root));
+    Window wiget_win = gdk_x11_surface_get_xid (surface);
+    XWindowAttributes attr;
+    Display *display = gdk_x11_display_get_xdisplay (gdk_surface_get_display
(surface));
+    XGetWindowAttributes(display, wiget_win, &attr);
+
+    Window child_win = None;
+    XTranslateCoordinates(display, wiget_win, attr.root, widget_x, widget_y,
x, y, &child_win);
+}
+
+
+static gboolean key_snooper (GtkWidget *widget, GdkEvent *event, gpointer
data)
+{
+    scim_bridge_pdebugln (7, "key_snooper ()");
+
+    GdkEventType type = gdk_event_get_event_type(event);
+    if (focused_imcontext && scim_bridge_client_is_messenger_opened () &&
+        (type == GDK_KEY_PRESS || type == GDK_KEY_RELEASE)) { //&&
+        //!(event->send_event & SEND_EVENT_MASK)) {
+        if (focused_imcontext->client_widget) {
+            // TODO get cliet_wiget's origin
+            int new_widget_x = 0;
+            int new_widget_y = 0;
+            widget_get_origin (focused_imcontext->client_widget,
&new_widget_x, &new_widget_y);
+
+            if (focused_imcontext->window_x != new_widget_x ||
focused_imcontext->window_y != new_widget_y) {
+                scim_bridge_pdebugln (1,
+                    "The cursor location is changed: x = %d + %d\ty = %d +
%d",
+                    new_widget_x, focused_imcontext->cursor_x, new_widget_y,
focused_imcontext->cursor_y);
+
+                if (set_cursor_location (focused_imcontext, new_widget_x,
new_widget_y, focused_imcontext->cursor_x, focused_imcontext->cursor_y)) {
+                    scim_bridge_perrorln ("An IOException at key_snooper
()");
+                    return FALSE;
+                }
+            }
+        }
+
+        boolean consumed = FALSE;
+        if (filter_key_event (focused_imcontext, event, &consumed)) {
+            scim_bridge_perrorln ("An IOException at key_snooper ()");
+            return FALSE;
+        } else {
+            if (consumed) {
+                g_signal_emit_by_name (focused_imcontext, "preedit-changed");
+                return TRUE;
+            }
+        }
+    }
+
+    return FALSE;
+}
+
+
+static boolean is_precise_cursor_enabled ()
+{
+    static boolean first_time = TRUE;
+    static boolean precise_cursor_enabled = FALSE;
+
+    if (first_time) {
+        char *env_precise_cursor_enabled = getenv
("SCIM_BRIDGE_PRECISE_CURSOR_ENABLED");
+        if (env_precise_cursor_enabled != NULL) scim_bridge_string_to_boolean
(&precise_cursor_enabled, env_precise_cursor_enabled);
+        first_time = FALSE;
+    }
+
+    return precise_cursor_enabled;
+}
+
+/* Bindings */
+void scim_bridge_client_imcontext_set_id (ScimBridgeClientIMContext
*imcontext, scim_bridge_imcontext_id_t new_id)
+{
+    imcontext->id = new_id;
+}
+
+
+scim_bridge_imcontext_id_t scim_bridge_client_imcontext_get_id (const
ScimBridgeClientIMContext *imcontext)
+{
+    return imcontext->id;
+}
+
+
+void scim_bridge_client_imcontext_set_preedit_string
(ScimBridgeClientIMContext *imcontext, const char *preedit_string)
+{
+    if (imcontext->preedit_string != NULL && preedit_string != NULL &&
!strcmp (imcontext->preedit_string, preedit_string))
+        return;
+
+    size_t preedit_string_length;
+    if (preedit_string != NULL) {
+        preedit_string_length = strlen (preedit_string);
+    } else {
+        preedit_string_length = 0;
+    }
+    if (imcontext->preedit_string_capacity <= preedit_string_length) {
+        imcontext->preedit_string_capacity = preedit_string_length;
+        free (imcontext->preedit_string);
+        imcontext->preedit_string = malloc (sizeof (char) * (imcontext-
>preedit_string_capacity + 1));
+    }
+    if (preedit_string_length > 0) {
+        strcpy (imcontext->preedit_string, preedit_string);
+    } else {
+        imcontext->preedit_string[0] = '\0';
+    }
+}
+
+
+void scim_bridge_client_imcontext_set_preedit_shown
(ScimBridgeClientIMContext *imcontext, boolean preedit_shown)
+{
+    imcontext->preedit_shown = preedit_shown;
+    if (!preedit_shown) {
+        free (imcontext->preedit_string);
+        imcontext->preedit_string = malloc (sizeof (char));
+        imcontext->preedit_string[0] = '\0';
+        imcontext->preedit_string_capacity = 0;
+        imcontext->preedit_cursor_position = 0;
+        if (imcontext->preedit_attributes != NULL) {
+            pango_attr_list_unref (imcontext->preedit_attributes);
+            imcontext->preedit_attributes = NULL;
+        }
+    }
+}
+
+void scim_bridge_client_imcontext_set_preedit_cursor_position
(ScimBridgeClientIMContext *imcontext, int cursor_position)
+{
+    imcontext->preedit_cursor_position = cursor_position;
+}
+
+
+void scim_bridge_client_imcontext_set_preedit_attributes
(ScimBridgeClientIMContext *imcontext, ScimBridgeAttribute** const
preedit_attributes, int attribute_count)
+{   
+    if (imcontext->preedit_attributes != NULL)
+        pango_attr_list_unref (imcontext->preedit_attributes);
+    
+    imcontext->preedit_attributes = pango_attr_list_new ();
+    
+    int preedit_string_length = 0;
+    int preedit_wstring_length = 0;
+    if (imcontext->preedit_string != NULL) {
+        preedit_string_length = strlen (imcontext->preedit_string);
+        preedit_wstring_length = g_utf8_strlen (imcontext->preedit_string, -
1);
+    }
+    
+    boolean *has_attribute = alloca (sizeof (boolean) *
preedit_string_length);
+    int i;
+    for (i = 0; i < preedit_string_length; ++i) {
+        has_attribute[i] = FALSE;
+    }
+
+    for (i = 0; i < attribute_count; ++i) {
+        const ScimBridgeAttribute *attr = preedit_attributes[i];
+        const int begin_pos = scim_bridge_attribute_get_begin (attr);
+        const int end_pos = scim_bridge_attribute_get_end (attr);
+
+        if (begin_pos <= end_pos && 0 <= begin_pos && end_pos <=
preedit_wstring_length) {
+            const int start_index = g_utf8_offset_to_pointer (imcontext-
>preedit_string, begin_pos) - imcontext->preedit_string;
+            const int end_index = g_utf8_offset_to_pointer (imcontext-
>preedit_string, end_pos) - imcontext->preedit_string;
+
+            const scim_bridge_attribute_type_t attr_type =
scim_bridge_attribute_get_type (attr);
+            const scim_bridge_attribute_value_t attr_value =
scim_bridge_attribute_get_value (attr);
+
+            boolean valid_attribute = FALSE;
+            if (attr_type == ATTRIBUTE_DECORATE) {
+                if (attr_value == SCIM_BRIDGE_ATTRIBUTE_DECORATE_UNDERLINE) {
+                    valid_attribute = TRUE;
+
+                    PangoAttribute *pango_attr = pango_attr_underline_new
(PANGO_UNDERLINE_SINGLE);
+                    pango_attr->start_index = start_index;
+                    pango_attr->end_index = end_index;
+                    pango_attr_list_insert (imcontext->preedit_attributes,
pango_attr);
+                } else if (attr_value ==
SCIM_BRIDGE_ATTRIBUTE_DECORATE_REVERSE) {
+                    valid_attribute = TRUE;
+
+                    PangoAttribute *pango_attr0 = pango_attr_foreground_new
(preedit_normal_background.red, preedit_normal_background.green,
preedit_normal_background.blue);
+                    pango_attr0->start_index = start_index;
+                    pango_attr0->end_index = end_index;
+                    pango_attr_list_insert (imcontext->preedit_attributes,
pango_attr0);
+
+                    PangoAttribute *pango_attr1 = pango_attr_background_new
(preedit_normal_foreground.red, preedit_normal_foreground.green,
preedit_normal_foreground.blue);
+                    pango_attr1->start_index = start_index;
+                    pango_attr1->end_index = end_index;
+                    pango_attr_list_insert (imcontext->preedit_attributes,
pango_attr1);
+                } else if (attr_value ==
SCIM_BRIDGE_ATTRIBUTE_DECORATE_HIGHLIGHT) {
+                    valid_attribute = TRUE;
+
+                    PangoAttribute *pango_attr0 = pango_attr_foreground_new
(preedit_active_foreground.red, preedit_active_foreground.green,
preedit_active_foreground.blue);
+                    pango_attr0->start_index = start_index;
+                    pango_attr0->end_index = end_index;
+                    pango_attr_list_insert (imcontext->preedit_attributes,
pango_attr0);
+
+                    PangoAttribute *pango_attr1 = pango_attr_background_new
(preedit_active_background.red, preedit_active_background.green,
preedit_active_background.blue);
+                    pango_attr1->start_index = start_index;
+                    pango_attr1->end_index = end_index;
+                    pango_attr_list_insert (imcontext->preedit_attributes,
pango_attr1);
+                } else {
+                    scim_bridge_perrorln ("Unknown preedit decoration!");
+                }
+            } else if (attr_type == ATTRIBUTE_FOREGROUND) {
+                valid_attribute = TRUE;
+
+                const unsigned int red = scim_bridge_attribute_get_red (attr)
* 256;
+                const unsigned int green = scim_bridge_attribute_get_green
(attr) * 256;
+                const unsigned int blue = scim_bridge_attribute_get_blue
(attr) * 256;
+
+                PangoAttribute *pango_attr = pango_attr_foreground_new (red,
green, blue);
+                pango_attr->start_index = start_index;
+                pango_attr->end_index = end_index;
+                pango_attr_list_insert (imcontext->preedit_attributes,
pango_attr);
+            } else if (attr_type == ATTRIBUTE_BACKGROUND) {
+                valid_attribute = TRUE;
+
+                const unsigned int red = scim_bridge_attribute_get_red (attr)
* 256;
+                const unsigned int green = scim_bridge_attribute_get_green
(attr) * 256;
+                const unsigned int blue = scim_bridge_attribute_get_blue
(attr) * 256;
+
+                PangoAttribute *pango_attr = pango_attr_background_new (red,
green, blue);
+                pango_attr->start_index = start_index;
+                pango_attr->end_index = end_index;
+                pango_attr_list_insert (imcontext->preedit_attributes,
pango_attr);
+            }
+
+            if (valid_attribute) {
+                int j;
+                for (j = start_index; j < end_index; ++j) {
+                    has_attribute[j] = TRUE;
+                }
+            }
+        }
+
+    }
+
+    // Add underlines for the all characters without attributes.
+    for (i = 0; i < preedit_string_length; ++i) {
+        if (has_attribute[i] == FALSE) {
+            PangoAttribute *pango_attr = pango_attr_underline_new
(PANGO_UNDERLINE_SINGLE);
+            pango_attr->start_index = i;
+            for (; i < preedit_string_length && has_attribute[i] == FALSE;
++i);
+            pango_attr->end_index = i;
+            pango_attr_list_insert (imcontext->preedit_attributes,
pango_attr);
+        }
+    }
+}
+
+
+void scim_bridge_client_imcontext_update_preedit (ScimBridgeClientIMContext
*imcontext)
+{
+    if (imcontext->preedit_shown && !imcontext->preedit_started) {
+        g_signal_emit_by_name ((ScimBridgeClientIMContext*) imcontext,
"preedit-start");
+        imcontext->preedit_started = TRUE;
+    }
+    
+    if (is_precise_cursor_enabled ()) {
+        const size_t old_cursor_position = imcontext-
>preedit_cursor_position;
+        imcontext->preedit_cursor_position = 0;
+        if (imcontext->preedit_string != NULL)
+            imcontext->preedit_cursor_position = g_utf8_strlen (imcontext-
>preedit_string, -1);
+        
+        imcontext->preedit_cursor_flicking = TRUE;
+        g_signal_emit_by_name ((ScimBridgeClientIMContext*) imcontext,
"preedit-changed");
+        
+        imcontext->preedit_cursor_position = old_cursor_position;
+        imcontext->preedit_cursor_flicking = FALSE;
+    }
+    
+    g_signal_emit_by_name ((ScimBridgeClientIMContext*) imcontext, "preedit-
changed");
+    
+    if (!imcontext->preedit_shown && imcontext->preedit_started) {
+        g_signal_emit_by_name ((ScimBridgeClientIMContext*) imcontext,
"preedit-end");
+        imcontext->preedit_started = FALSE;
+    }
+}
+
+
+void scim_bridge_client_imcontext_set_commit_string
(ScimBridgeClientIMContext *imcontext, const char *commit_string)
+{
+    size_t commit_string_length;
+    if (commit_string != NULL) {
+        commit_string_length = strlen (commit_string);
+    } else {
+        commit_string_length = 0;
+    }
+    
+    if (imcontext->commit_string_capacity <= commit_string_length) {
+        imcontext->commit_string_capacity = commit_string_length;
+        free (imcontext->commit_string);
+        imcontext->commit_string = malloc (sizeof (char) * (imcontext-
>commit_string_capacity + 1));
+    }
+    if (commit_string_length > 0) {
+        strcpy (imcontext->commit_string, commit_string);
+    } else {
+        imcontext->commit_string[0] = '\0';
+    }
+}
+
+
+void scim_bridge_client_imcontext_commit (ScimBridgeClientIMContext
*imcontext)
+{
+    g_signal_emit_by_name ((ScimBridgeClientIMContext*) imcontext, "commit",
imcontext->commit_string);
+}
+
+
+void scim_bridge_client_imcontext_beep (ScimBridgeClientIMContext *imcontext)
+{
+    gtk_widget_error_bell(imcontext->client_widget);
+}
+
+
+boolean scim_bridge_client_imcontext_get_surrounding_text
(ScimBridgeClientIMContext *imcontext, int before_max, int after_max, char
**string, int *cursor_position)
+{
+    char *str;
+    int cur_pos_in_utf8, an_pos_in_utf8;
+
+    if (gtk_im_context_get_surrounding_with_selection (GTK_IM_CONTEXT
(imcontext),
+                                                       &str,
+                                                       &cur_pos_in_utf8,
+                                                       &an_pos_in_utf8)) {
+        const size_t fetch_wstr_length = g_utf8_strlen (str, -1);
+        const size_t after_wstr_length = g_utf8_strlen (str +
cur_pos_in_utf8, an_pos_in_utf8);
+        const size_t before_wstr_length = fetch_wstr_length -
after_wstr_length;
+
+        size_t before_copy_wstr_length;
+        size_t after_copy_wstr_length;
+        if (after_wstr_length > after_max) {
+            after_copy_wstr_length = after_max;
+        } else {
+            after_copy_wstr_length = after_wstr_length;
+        }
+        if (before_wstr_length > before_max) {
+            before_copy_wstr_length = before_max;
+        } else {
+            before_copy_wstr_length = before_wstr_length;
+        }
+
+        const size_t begin_wstr_index = before_wstr_length -
before_copy_wstr_length;
+        const size_t end_wstr_index = fetch_wstr_length - (after_wstr_length
- after_copy_wstr_length);
+
+        char* begin_str_ptr = g_utf8_offset_to_pointer (str,
begin_wstr_index);
+        char* end_str_ptr = g_utf8_offset_to_pointer (str, end_wstr_index);
+        size_t str_length = end_str_ptr - begin_str_ptr;
+
+        *string = malloc (sizeof (char) * (str_length + 1));
+        strncpy (*string, begin_str_ptr, str_length);
+        (*string)[str_length] = '\0';
+        *cursor_position = before_copy_wstr_length;
+
+        g_free (str);
+        return TRUE;
+    } else {
+        *string = NULL;
+
+        return FALSE;
+    }
+}
+
+
+boolean scim_bridge_client_imcontext_delete_surrounding_text
(ScimBridgeClientIMContext *imcontext, int offset, int length)
+{
+    boolean retval = gtk_im_context_delete_surrounding (GTK_IM_CONTEXT
(imcontext), offset, length);
+    return retval;
+}
+
+
+boolean scim_bridge_client_imcontext_replace_surrounding_text
(ScimBridgeClientIMContext *imcontext, int cursor_position, const char
*string)
+{
+    gtk_im_context_set_surrounding_with_selection (GTK_IM_CONTEXT
(imcontext),
+                                                   string,
+                                                   -1,
+                                                   cursor_position,
+                                                   cursor_position);
+    return TRUE;
+}
+
+void scim_bridge_client_imcontext_forward_key_event
(ScimBridgeClientIMContext *imcontext, const ScimBridgeKeyEvent *key_event)
+{ 
+    scim_bridge_pdebugln (7, "scim_bridge_client_imcontext_forward_key_event:
NOT IMPLEMENTED YET");
+}
+
+
+void scim_bridge_client_imcontext_imengine_status_changed
(ScimBridgeClientIMContext *imcontext, boolean enabled)
+{
+    if (imcontext->preedit_shown) {
+        if (imcontext->enabled) {
+            scim_bridge_client_imcontext_set_preedit_shown (imcontext,
FALSE);
+            scim_bridge_client_imcontext_update_preedit (imcontext);
+        }
+    }
+    imcontext->enabled = enabled;
+}
+
+
+/* Class Implementations */
+void scim_bridge_client_imcontext_static_initialize ()
+{
+    GdkRGBA color;
+    g_warn_if_fail(gdk_rgba_parse (&color, "gray92"));
+    preedit_normal_background = (Color){color.red * 65535, color.green *
65535, color.blue * 65535};
+    g_warn_if_fail(gdk_rgba_parse (&color, "black"));
+    preedit_normal_foreground = (Color){color.red * 65535, color.green *
65535, color.blue * 65535};
+    g_warn_if_fail(gdk_rgba_parse (&color, "light blue"));
+    preedit_active_background = (Color){color.red * 65535, color.green *
65535, color.blue * 65535};
+    g_warn_if_fail(gdk_rgba_parse (&color, "black"));
+    preedit_active_foreground = (Color){color.red * 65535, color.green *
65535, color.blue * 65535};
+
+    focused_imcontext = NULL;
+}
+
+
+void scim_bridge_client_imcontext_static_finalize ()
+{
+    focused_imcontext = NULL;
+}
+
+
+void scim_bridge_client_imcontext_connection_opened ()
+{
+}
+
+
+void scim_bridge_client_imcontext_connection_closed ()
+{
+    if (focused_imcontext != NULL)
scim_bridge_client_imcontext_set_preedit_shown (focused_imcontext, FALSE);
+}
+
+
+void scim_bridge_client_imcontext_class_initialize
(ScimBridgeClientIMContextClass *klass, gpointer *klass_data)
+{
+    root_klass = (GObjectClass *) g_type_class_peek_parent (klass);
+
+    GtkIMContextClass *gtk_im_klass = GTK_IM_CONTEXT_CLASS (klass);
+    gtk_im_klass->set_client_widget =
scim_bridge_client_imcontext_set_client_widget;
+    gtk_im_klass->filter_keypress =
scim_bridge_client_imcontext_filter_key_event;
+    gtk_im_klass->reset = scim_bridge_client_imcontext_reset;
+    gtk_im_klass->get_preedit_string =
scim_bridge_client_imcontext_get_preedit_string;
+    gtk_im_klass->focus_in  = scim_bridge_client_imcontext_focus_in;
+    gtk_im_klass->focus_out = scim_bridge_client_imcontext_focus_out;
+    gtk_im_klass->set_cursor_location =
scim_bridge_client_imcontext_set_cursor_location;
+    gtk_im_klass->set_use_preedit =
scim_bridge_client_imcontext_set_preedit_enabled;
+
+    GObjectClass *gobject_klass = G_OBJECT_CLASS (klass);
+    gobject_klass->finalize = scim_bridge_client_imcontext_finalize;
+}
+
+
+GType scim_bridge_client_imcontext_get_type ()
+{
+    return class_type;
+}
+
+
+void scim_bridge_client_imcontext_register_type (GIOModule *io_module)
+{
+    scim_bridge_pdebugln (2, "scim_bridge_client_imcontext_register_type
()");
+
+    static const GTypeInfo klass_info = {
+        sizeof (ScimBridgeClientIMContextClass),
+        /* no base class initializer */
+        NULL,
+        /* no base class finalizer */
+        NULL,
+        /* class initializer */
+        (GClassInitFunc) scim_bridge_client_imcontext_class_initialize,
+        /* no class finalizer */
+        NULL,
+        /* no class data */
+        NULL,
+        sizeof (ScimBridgeClientIMContext),
+        0,
+        /* object initizlier */
+        (GInstanceInitFunc) scim_bridge_client_imcontext_initialize,
+        0
+    };
+
+    class_type = g_type_module_register_type (G_TYPE_MODULE(io_module),
+                                              GTK_TYPE_IM_CONTEXT,
+                                              "ScimBridgeClientIMContext",
+                                              &klass_info,
+                                              0);
+}
+
+
+GtkIMContext *scim_bridge_client_imcontext_new ()
+{
+    scim_bridge_pdebugln (4, "scim_bridge_client_imcontext_new ()");
+
+    ScimBridgeClientIMContext *ic = SCIM_BRIDGE_CLIENT_IMCONTEXT
(g_object_new (GTK_TYPE_SCIM_CLIENT_IMCONTEXT, NULL));
+    return GTK_IM_CONTEXT (ic);
+}
+
+
+void scim_bridge_client_imcontext_initialize (ScimBridgeClientIMContext
*imcontext, ScimBridgeClientIMContextClass *klass)
+{
+    scim_bridge_pdebugln (5, "scim_bridge_client_imcontext_initialize  ()");
+
+    /* slave exists for using gtk+'s table based input method */
+    imcontext->slave_preedit = FALSE;
+    imcontext->slave = gtk_im_context_simple_new ();
+    g_signal_connect(G_OBJECT(imcontext->slave),
+                     "commit",
+                     G_CALLBACK(gtk_im_slave_commit_cb),
+                     imcontext);
+    
+    g_signal_connect(G_OBJECT(imcontext->slave),
+                     "preedit-changed",
+                     G_CALLBACK(gtk_im_slave_preedit_changed_cb),
+                     imcontext);
+    
+    g_signal_connect(G_OBJECT(imcontext->slave),
+                     "preedit-start",
+                     G_CALLBACK(gtk_im_slave_preedit_start_cb),
+                     imcontext);
+    
+    g_signal_connect(G_OBJECT(imcontext->slave),
+                     "preedit-end",
+                     G_CALLBACK(gtk_im_slave_preedit_end_cb),
+                     imcontext);
+
+    imcontext->preedit_shown = FALSE;
+    imcontext->preedit_started = FALSE;
+    
+    imcontext->preedit_cursor_position = 0;
+    imcontext->preedit_cursor_flicking = FALSE;
+
+    imcontext->preedit_string = malloc (sizeof (char));
+    imcontext->preedit_string[0] = '\0';
+    imcontext->preedit_string_capacity = 0;
+
+    imcontext->preedit_attributes = NULL;
+
+    imcontext->commit_string = malloc (sizeof (char));
+    imcontext->commit_string[0] = '\0';
+    imcontext->commit_string_capacity = 0;
+
+    imcontext->enabled = FALSE;
+
+    imcontext->client_widget = NULL;
+
+    imcontext->id = -1;
+
+    if (!scim_bridge_client_is_messenger_opened ()) {
+        scim_bridge_perrorln ("The messenger is now down");
+    } else if (scim_bridge_client_register_imcontext (imcontext)) {
+        scim_bridge_perrorln ("Failed to register the IMContext");
+    } else {
+        scim_bridge_pdebugln (1, "IMContext registered: id = %d", imcontext-
>id);
+    }
+}
+
+
+void scim_bridge_client_imcontext_finalize (GObject *object)
+{
+    scim_bridge_pdebugln (5, "scim_bridge_client_imcontext_finalize ()");
+
+    ScimBridgeClientIMContext *imcontext = SCIM_BRIDGE_CLIENT_IMCONTEXT
(object);
+
+    if (imcontext == focused_imcontext)
scim_bridge_client_imcontext_focus_out (GTK_IM_CONTEXT (imcontext));
+
+    if (!scim_bridge_client_is_messenger_opened ()) {
+        scim_bridge_perrorln ("The messenger is now down");
+    } else if (scim_bridge_client_deregister_imcontext (imcontext)) {
+        scim_bridge_perrorln ("Failed to deregister an IMContext");
+    } else {
+        scim_bridge_pdebugln (3, "IMContext deregistered: id = %d",
imcontext->id);
+    }
+
+    if (imcontext->client_widget) g_object_unref (imcontext->client_widget);
+
+    free (imcontext->preedit_string);
+    free (imcontext->commit_string);
+
+    if (imcontext->preedit_attributes != NULL)
+        pango_attr_list_unref (imcontext->preedit_attributes);
+    
+    imcontext->preedit_attributes = NULL;
+    
+    g_signal_handlers_disconnect_by_func(imcontext->slave,
+                                         (void *)gtk_im_slave_commit_cb,
+                                         (void *)imcontext);
+    g_signal_handlers_disconnect_by_func(imcontext->slave,
+                                         (void
*)gtk_im_slave_preedit_changed_cb,
+                                         (void *)imcontext);
+    g_signal_handlers_disconnect_by_func(imcontext->slave,
+                                         (void
*)gtk_im_slave_preedit_start_cb,
+                                         (void *)imcontext);
+    g_signal_handlers_disconnect_by_func(imcontext->slave,
+                                         (void *)gtk_im_slave_preedit_end_cb,
+                                         (void *)imcontext);
+    g_object_unref(imcontext->slave);
+
+    root_klass->finalize (object);
+}
+
+
+/* Class functions */
+gboolean scim_bridge_client_imcontext_filter_key_event (GtkIMContext
*context, GdkEvent *event)
+{
+    scim_bridge_pdebugln (8, "scim_bridge_client_imcontext_filter_key_event
()");
+
+    ScimBridgeClientIMContext *imcontext = SCIM_BRIDGE_CLIENT_IMCONTEXT
(context);
+
+    boolean ret = FALSE;
+    if (imcontext) {
+        ret = key_snooper(0, event, 0);
+
+        if (imcontext->slave) {
+            if (!ret) {
+                ret = gtk_im_context_filter_keypress (imcontext->slave,
event);
+            } else if (imcontext->slave_preedit) {
+                imcontext->slave_preedit = FALSE;
+                gtk_im_context_reset (imcontext->slave);
+            }
+        }
+
+    }
+
+    return ret;
+}
+
+
+void scim_bridge_client_imcontext_reset (GtkIMContext *context)
+{
+    scim_bridge_pdebugln (8, "scim_bridge_client_imcontext_reset ()");
+
+    ScimBridgeClientIMContext *imcontext = SCIM_BRIDGE_CLIENT_IMCONTEXT
(context);
+
+    if (imcontext != focused_imcontext) return;
+
+    if (scim_bridge_client_is_messenger_opened () && imcontext != NULL) {
+        if (scim_bridge_client_reset_imcontext (imcontext)) {
+            scim_bridge_perrorln ("An IOException occurred at
scim_bridge_client_imcontext_reset ()");
+        }
+    }
+}
+
+
+void scim_bridge_client_imcontext_get_preedit_string (GtkIMContext *context,
gchar **str, PangoAttrList **pango_attrs, gint *cursor_pos)
+{
+    scim_bridge_pdebugln (4, "scim_bridge_client_imcontext_get_preedit_string
()");
+
+    ScimBridgeClientIMContext *imcontext = SCIM_BRIDGE_CLIENT_IMCONTEXT
(context);
+
+    if (imcontext->slave_preedit) {
+        gtk_im_context_get_preedit_string (imcontext->slave, str,
pango_attrs, cursor_pos);
+        return;
+    }
+    
+    if (scim_bridge_client_is_messenger_opened () && imcontext != NULL &&
imcontext->preedit_shown) {
+        const size_t preedit_string_length = strlen (imcontext-
>preedit_string);
+        const size_t preedit_wstring_length = g_utf8_strlen (imcontext-
>preedit_string, -1);
+        
+        if (str) {
+            if (preedit_string_length > 0) {
+                *str = g_strdup (imcontext->preedit_string);
+            } else {
+                *str = g_strdup ("");
+            }
+        }
+        
+        if (cursor_pos) {
+            if (imcontext->preedit_cursor_position > preedit_wstring_length)
{
+                *cursor_pos = preedit_wstring_length;
+            } else {
+                *cursor_pos = imcontext->preedit_cursor_position;
+            }
+        }
+        
+        if (pango_attrs) {
+            *pango_attrs = imcontext->preedit_attributes;
+            pango_attr_list_ref (imcontext->preedit_attributes);
+        }
+    } else {
+        if (str) *str = g_strdup ("");
+        if (cursor_pos) *cursor_pos = 0;
+        if (pango_attrs) *pango_attrs = pango_attr_list_new ();
+    }
+}
+
+
+void scim_bridge_client_imcontext_focus_in (GtkIMContext *context)
+{
+    scim_bridge_pdebugln (8, "scim_bridge_client_imcontext_focus_in ()");
+
+    ScimBridgeClientIMContext *imcontext = SCIM_BRIDGE_CLIENT_IMCONTEXT
(context);
+    
+    if (focused_imcontext != NULL && focused_imcontext != imcontext) {
+        scim_bridge_client_imcontext_focus_out (GTK_IM_CONTEXT
(focused_imcontext));
+    }
+    focused_imcontext = imcontext;
+
+    if (!scim_bridge_client_is_messenger_opened () &&
scim_bridge_client_is_reconnection_enabled ()) {
+        scim_bridge_pdebugln (7, "Trying to open the connection again...");
+        scim_bridge_client_open_messenger ();
+    }
+
+    if (scim_bridge_client_is_messenger_opened () && imcontext != NULL) {
+        if (scim_bridge_client_change_focus (imcontext, TRUE)) {
+            scim_bridge_perrorln ("An IOException occurred at
scim_bridge_client_imcontext_focus_in ()");
+        }
+    }
+}
+
+
+void scim_bridge_client_imcontext_focus_out (GtkIMContext *context)
+{
+    scim_bridge_pdebugln (8, "scim_bridge_client_imcontext_focus_out ()");
+
+    ScimBridgeClientIMContext *imcontext = SCIM_BRIDGE_CLIENT_IMCONTEXT
(context);
+    focused_widget = NULL;
+
+    focused_imcontext = imcontext;
+    if (imcontext->preedit_shown) {
+        if (imcontext->enabled) {
+            scim_bridge_client_imcontext_set_preedit_shown (imcontext,
FALSE);
+            scim_bridge_client_imcontext_update_preedit (imcontext);
+        }
+    }
+    if (scim_bridge_client_is_messenger_opened () && imcontext != NULL) {
+        if (scim_bridge_client_change_focus (imcontext, FALSE)) {
+            scim_bridge_perrorln ("An IOException occurred at
scim_bridge_client_imcontext_focus_out ()");
+        }
+    }
+
+    focused_imcontext = NULL;
+}
+
+
+void scim_bridge_client_imcontext_set_client_widget (GtkIMContext *context,
GtkWidget *new_widget)
+{
+    scim_bridge_pdebugln (7, "scim_bridge_client_imcontext_set_client_widget
()");
+
+    ScimBridgeClientIMContext *imcontext = SCIM_BRIDGE_CLIENT_IMCONTEXT
(context);
+    if (!imcontext) {
+        return;
+    }
+
+    if (imcontext->client_widget) {
+        g_object_unref(imcontext->client_widget);
+    }
+
+    imcontext->client_widget = new_widget;
+    if (!new_widget) {
+        return;
+    }
+
+    g_object_ref (new_widget);
+    widget_get_origin (imcontext->client_widget, &imcontext->window_x,
&imcontext->window_y);
+}
+
+void scim_bridge_client_imcontext_set_cursor_location (GtkIMContext *context,
GdkRectangle *area)
+{
+    scim_bridge_pdebugln (4,
"scim_bridge_client_imcontext_set_cursor_location ()");
+
+    ScimBridgeClientIMContext *imcontext = SCIM_BRIDGE_CLIENT_IMCONTEXT
(context);
+    if (imcontext->preedit_cursor_flicking)
+        return;
+
+    if (imcontext != NULL && imcontext->client_widget != NULL) {
+        const int new_cursor_x = area->x + area->width;
+        const int new_cursor_y = area->y + area->height + 8;
+
+        int widget_x, widget_y;
+        widget_get_origin(imcontext->client_widget, &widget_x, &widget_y);
+
+        if (set_cursor_location (imcontext, widget_x, widget_y, new_cursor_x,
new_cursor_y)) {
+            scim_bridge_perrorln ("An IOException occurred at
scim_bridge_client_imcontext_set_cursor_location ()");
+        }
+    }
+}
+
+
+void scim_bridge_client_imcontext_set_preedit_enabled (GtkIMContext *context,
gboolean enabled)
+{
+    scim_bridge_pdebugln (8,
"scim_bridge_client_imcontext_set_preedit_enabled ()");
+
+    ScimBridgeClientIMContext *imcontext = SCIM_BRIDGE_CLIENT_IMCONTEXT
(context);
+
+    if (imcontext != NULL) {
+        if (scim_bridge_client_is_messenger_opened ()) {
+            if (scim_bridge_client_set_preedit_mode (imcontext, enabled ?
PREEDIT_EMBEDDED:PREEDIT_ANY)) {
+                scim_bridge_perrorln ("An IOException occurred at
scim_bridge_client_imcontext_set_preedit_enabled ()");
+            }
+        }
+    }
+}
+
+static void
+gtk_im_slave_commit_cb (
+    GtkIMContext *context,
+    const char *str,
+    ScimBridgeClientIMContext *imcontext
+) {
+    g_return_if_fail(str);
+    g_signal_emit_by_name(imcontext, "commit", str);
+}
+
+static void
+gtk_im_slave_preedit_changed_cb (
+    GtkIMContext *context,
+    ScimBridgeClientIMContext *imcontext
+) {
+    imcontext->slave_preedit = TRUE;
+    g_signal_emit_by_name(imcontext, "preedit-changed");
+}
+
+static void
+gtk_im_slave_preedit_start_cb (
+    GtkIMContext *context,
+    ScimBridgeClientIMContext *imcontext
+) {
+    imcontext->slave_preedit = TRUE;
+    g_signal_emit_by_name(imcontext, "preedit-start");
+}
+
+static void
+gtk_im_slave_preedit_end_cb (
+    GtkIMContext *context,
+    ScimBridgeClientIMContext *imcontext
+) {
+    imcontext->slave_preedit = FALSE;
+    g_signal_emit_by_name(imcontext, "preedit-end");
+}
\ 文件尾没有换行符
diff -Nru scim-1.4.18/extras/immodules/client-gtk/gtk4/scim-bridge-client-
imcontext-gtk.h scim-1.4.18+git20211204/extras/immodules/client-gtk/gtk4/scim-
bridge-client-imcontext-gtk.h
--- scim-1.4.18/extras/immodules/client-gtk/gtk4/scim-bridge-client-imcontext-
gtk.h   1969-12-31 19:00:00.000000000 -0500
+++ scim-1.4.18+git20211204/extras/immodules/client-gtk/gtk4/scim-bridge-
client-imcontext-gtk.h  2021-12-04 05:40:01.000000000 -0500
@@ -0,0 +1,111 @@
+/*
+ * SCIM Bridge
+ *
+ * Copyright (c) 2006 Ryo Dairiki <[email protected]>
+ *
+ *
+ * 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 and 
+ * appearing in the file LICENSE.LGPL included in the package of this file.
+ * You can also redistribute it and/or modify it under the terms of 
+ * the GNU General Public License as published by the Free Software
Foundation and 
+ * appearing in the file LICENSE.GPL included in the package of this file.
+ *
+ * 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.
+ */
+
+/**
+ * @file
+ * @author Ryo Dairiki <[email protected]>
+ * @brief This is the header for gtk imcontext of scim-bridge.
+ */
+
+
+#ifndef SCIMBRIDGECLIENTIMCONTEXTGTK_H_
+#define SCIMBRIDGECLIENTIMCONTEXTGTK_H_
+
+#include <gtk/gtk.h>
+#if GTK_CHECK_VERSION(3, 0, 0)
+#else
+#include <gtk/gtkimcontext.h>
+#endif
+
+#include <gdk/gdk.h>
+
+#include "scim-bridge.h"
+#include "scim-bridge-client-imcontext.h"
+
+#define
GTK_TYPE_SCIM_CLIENT_IMCONTEXT  (scim_bridge_client_imcontext_get_type ())
+#if GTK_CHECK_VERSION(3, 0, 0)
+#define SCIM_BRIDGE_CLIENT_IMCONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),
GTK_TYPE_SCIM_CLIENT_IMCONTEXT, ScimBridgeClientIMContext))
+#else
+#define SCIM_BRIDGE_CLIENT_IMCONTEXT(obj) (GTK_CHECK_CAST ((obj),
GTK_TYPE_SCIM_CLIENT_IMCONTEXT, ScimBridgeClientIMContext))
+#endif
+#define SCIM_BRIDGE_CLIENT_IMCONTEXT_CLASS(klass) (GTK_CHECK_CLASS_CAST
((klass), GTK_TYPE_SCIM_CLIENT_IMCONTEXT, ScimBridgeClientIMContextClass))
+#if GTK_CHECK_VERSION(3, 0, 0)
+#define IS_SCIM_BRIDGE_CLIENT_IMCONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE
((obj), GTK_TYPE_SCIM_CLIENT_IMCONTEXT))
+#else
+#define IS_SCIM_BRIDGE_CLIENT_IMCONTEXT(class) (GTK_CHECK_TYPE ((obj),
GTK_TYPE_SCIM_CLIENT_IMCONTEXT))
+#endif
+#define IS_SCIM_BRIDGE_CLIENT_IMCONTEXT_CLASS(klass) (GTK_CHECK_CLASS_TYPE
((klass), GTK_TYPE_SCIM_CLIENT_IMCONTEXT))
+#if GTK_CHECK_VERSION(3, 0, 0)
+#define SCIM_BRIDGE_CLIENT_IMCONTEXT_GET_CLASS(obj)
(G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SCIM_CLIENT_IMCONTEXT,
ScimBridgeClientIMContextClass))
+#else
+#define SCIM_BRIDGE_CLIENT_IMCONTEXT_GET_CLASS(obj) (GTK_CHECK_GET_CLASS
((obj), GTK_TYPE_SCIM_CLIENT_IMCONTEXT, ScimBridgeClientIMContextClass))
+#endif
+
+struct _ScimBridgeClientIMContextClass
+{
+    GtkIMContextClass parent_class;
+};
+
+/**
+ * IMContext class for gtk client.
+ */
+typedef struct _ScimBridgeClientIMContextClass
ScimBridgeClientIMContextClass;
+
+/**
+ * Initialize IMContext class itself.
+ */
+void scim_bridge_client_imcontext_static_initialize ();
+
+/**
+ * Finalize IMContext class itself.
+ */
+void scim_bridge_client_imcontext_static_finalize ();
+
+/**
+ * The connection with the agent is opened.
+ */
+void scim_bridge_client_imcontext_connection_opened ();
+
+/**
+ * The connection with the agent is closed.
+ */
+void scim_bridge_client_imcontext_connection_closed ();
+
+/**
+ * Allocate an IMContext.
+ *
+ * @return new IMContext.
+ */
+GtkIMContext *scim_bridge_client_imcontext_new ();
+
+/**
+ * Get the type value of IMContexts.
+ *
+ * @return The type value of IMContexts.
+ */
+GType scim_bridge_client_imcontext_get_type ();
+
+/**
+ * Register the type value for IMContexts.
+ *
+ * @param type_module The type module.
+ */
+void scim_bridge_client_imcontext_register_type (GIOModule *io_module);
+
+#endif                                           
/*SCIMBRIDGECLIENTIMCONTEXTGTK_H_*/
diff -Nru scim-1.4.18/extras/immodules/client-gtk/gtk4/scim-bridge-client-key-
event-utility-gtk.c scim-1.4.18+git20211204/extras/immodules/client-
gtk/gtk4/scim-bridge-client-key-event-utility-gtk.c
--- scim-1.4.18/extras/immodules/client-gtk/gtk4/scim-bridge-client-key-event-
utility-gtk.c   1969-12-31 19:00:00.000000000 -0500
+++ scim-1.4.18+git20211204/extras/immodules/client-gtk/gtk4/scim-bridge-
client-key-event-utility-gtk.c  2021-12-04 05:40:01.000000000 -0500
@@ -0,0 +1,132 @@
+/*
+ * SCIM Bridge
+ *
+ * Copyright (c) 2006 Ryo Dairiki <[email protected]>
+ *
+ *
+ * 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 and 
+ * appearing in the file LICENSE.LGPL included in the package of this file.
+ * You can also redistribute it and/or modify it under the terms of 
+ * the GNU General Public License as published by the Free Software
Foundation and 
+ * appearing in the file LICENSE.GPL included in the package of this file.
+ *
+ * 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.
+ */
+
+#include <sys/time.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkkeysyms.h>
+
+#ifdef GDK_WINDOWING_X11 
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#include <gdk/x11/gdkx.h>
+#endif
+
+#include "scim-bridge-client-key-event-utility-gtk.h"
+#include "scim-bridge-key-event.h"
+
+/* Implementations */
+void scim_bridge_key_event_bridge_to_gdk (GdkEvent *gdk_key_event,
+                                          GtkWidget *client_widget,
+                                          const ScimBridgeKeyEvent
*key_event)
+{
+//    gdk_key_event->state = 0;
+//    if (scim_bridge_key_event_is_shift_down (key_event)) gdk_key_event-
>state |= GDK_SHIFT_MASK;
+//    if (scim_bridge_key_event_is_caps_lock_down (key_event)) gdk_key_event-
>state |= GDK_LOCK_MASK;
+//    if (scim_bridge_key_event_is_control_down (key_event)) gdk_key_event-
>state |= GDK_CONTROL_MASK;
+//    if (scim_bridge_key_event_is_alt_down (key_event)) gdk_key_event->state
|= GDK_MOD1_MASK;
+//    if (scim_bridge_key_event_is_num_lock_down (key_event)) gdk_key_event-
>state |= GDK_MOD2_MASK;
+//
+//    if (scim_bridge_key_event_is_pressed (key_event)) {
+//        gdk_key_event->type = GDK_KEY_PRESS;
+//    } else {
+//        gdk_key_event->type = GDK_KEY_RELEASE;
+//        gdk_key_event->state |= GDK_RELEASE_MASK;
+//    }
+//
+//    gdk_key_event->widget = client_widget;
+//
+//    struct timeval current_time;
+//    gettimeofday (&current_time, NULL);
+//
+//    gdk_key_event->time = current_time.tv_sec * 1000 + current_time.tv_usec
/ 1000;
+//    gdk_key_event->keyval = scim_bridge_key_event_get_code (key_event);
+//    gdk_key_event->length = 0;
+//    gdk_key_event->string = 0;
+//
+//    GdkKeymap *key_map = get_gdk_keymap (gdk_key_event->widget);
+//
+//    GdkKeymapKey *keys;
+//    gint n_keys;
+//
+//    if (gdk_keymap_get_entries_for_keyval (key_map, gdk_key_event->keyval,
&keys, &n_keys)) {
+//        gdk_key_event->hardware_keycode = keys[0].keycode;
+//        gdk_key_event->group = keys [0].group;
+//    } else {
+//        gdk_key_event->hardware_keycode = 0;
+//        gdk_key_event->group = 0;
+//    }
+}
+
+
+void scim_bridge_key_event_gdk_to_bridge (ScimBridgeKeyEvent
*bridge_key_event,
+                                          GtkWidget *widget,
+                                          const GdkEvent *key_event)
+{
+    // Use Key Symbole provided by gtk.
+    guint keyval = gdk_key_event_get_keyval((GdkEvent *) key_event);
+    GdkModifierType state = gdk_event_get_modifier_state((GdkEvent *)
key_event);
+    scim_bridge_key_event_set_code (bridge_key_event,
(scim_bridge_key_code_t) keyval);
+
+    scim_bridge_key_event_clear_modifiers (bridge_key_event);
+    if (state & GDK_SHIFT_MASK || keyval == GDK_KEY_Shift_L || keyval ==
GDK_KEY_Shift_R)
+        scim_bridge_key_event_set_shift_down (bridge_key_event, TRUE);
+    if (state & GDK_LOCK_MASK || keyval == GDK_KEY_Caps_Lock)
+        scim_bridge_key_event_set_caps_lock_down (bridge_key_event, TRUE);
+    if (state & GDK_CONTROL_MASK || keyval == GDK_KEY_Control_L || keyval ==
GDK_KEY_Control_R)
+        scim_bridge_key_event_set_control_down (bridge_key_event, TRUE);
+    if (state & GDK_ALT_MASK || keyval == GDK_KEY_Alt_L || keyval ==
GDK_KEY_Alt_R)
+        scim_bridge_key_event_set_alt_down (bridge_key_event, TRUE);
+    if (gdk_device_get_num_lock_state(gdk_event_get_device((GdkEvent *)
key_event)))
+        scim_bridge_key_event_set_num_lock_down (bridge_key_event, TRUE);
+
+
+    if (gdk_event_get_event_type((GdkEvent *) key_event) != GDK_KEY_RELEASE)
{
+        scim_bridge_key_event_set_pressed (bridge_key_event, TRUE);
+    } else {
+        scim_bridge_key_event_set_pressed (bridge_key_event, FALSE);
+    }
+    
+#ifdef GDK_WINDOWING_X11
+    GdkX11Display *display = NULL;
+
+    if (widget != NULL) {
+        display = GDK_X11_DISPLAY (gtk_widget_get_display(widget));
+    } else {
+        display = GDK_X11_DISPLAY (gdk_display_get_default ());
+    }
+    
+    if (scim_bridge_key_event_get_code (bridge_key_event) ==
SCIM_BRIDGE_KEY_CODE_backslash) {
+        boolean kana_ro = FALSE;
+        int keysym_size = 0;
+        KeySym *keysyms = XGetKeyboardMapping (
+            gdk_x11_display_get_xdisplay(display),
+            gdk_key_event_get_keycode((GdkEvent *) key_event),
+            1,
+            &keysym_size);
+        if (keysyms != NULL) {
+            kana_ro = (keysyms[0] == XK_backslash && keysyms[1] ==
XK_underscore);
+            XFree (keysyms);
+        }
+        scim_bridge_key_event_set_quirk_enabled (bridge_key_event,
SCIM_BRIDGE_KEY_QUIRK_KANA_RO, kana_ro);
+    }
+#endif
+}
diff -Nru scim-1.4.18/extras/immodules/client-gtk/gtk4/scim-bridge-client-key-
event-utility-gtk.h scim-1.4.18+git20211204/extras/immodules/client-
gtk/gtk4/scim-bridge-client-key-event-utility-gtk.h
--- scim-1.4.18/extras/immodules/client-gtk/gtk4/scim-bridge-client-key-event-
utility-gtk.h   1969-12-31 19:00:00.000000000 -0500
+++ scim-1.4.18+git20211204/extras/immodules/client-gtk/gtk4/scim-bridge-
client-key-event-utility-gtk.h  2021-12-04 05:40:01.000000000 -0500
@@ -0,0 +1,54 @@
+/*
+ * SCIM Bridge
+ *
+ * Copyright (c) 2006 Ryo Dairiki <[email protected]>
+ *
+ *
+ * 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 and 
+ * appearing in the file LICENSE.LGPL included in the package of this file.
+ * You can also redistribute it and/or modify it under the terms of 
+ * the GNU General Public License as published by the Free Software
Foundation and 
+ * appearing in the file LICENSE.GPL included in the package of this file.
+ *
+ * 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.
+ */
+
+/**
+ * @file
+ * @author Ryo Dairiki <[email protected]>
+ * @brief This is the header of the functions to translate key events between
scim-bridge and gtk.
+ */
+
+
+#ifndef SCIMBRIDGECLIENTKEYEVENTUTILITYGTK_H_
+#define SCIMBRIDGECLIENTKEYEVENTUTILITYGTK_H_
+
+#include <gdk/gdk.h>
+
+#include "scim-bridge.h"
+#include "scim-bridge-key-event.h"
+
+/**
+ * Translate a key event from scim-bridge into gdk.
+ *
+ * @param gdk_key_event A key event of gdk.
+ * @param client_wiget The gdk window for the key event.
+ * @param key_event The key event from scim-bridge.
+ */
+void scim_bridge_key_event_bridge_to_gdk (GdkEvent *gdk_key_event, GtkWidget
*client_wiget, const ScimBridgeKeyEvent *key_event);
+
+
+/**
+ * Translate a key event from gdk into scim-bridge.
+ *
+ * @param bridge_key_event A key event of scim-bridge.
+ * @param client_wiget The gdk window for the key event.
+ * @param key_event The key event from gdk.
+ */
+void scim_bridge_key_event_gdk_to_bridge (ScimBridgeKeyEvent
*bridge_key_event, GtkWidget *client_wiget, const GdkEvent *key_event);
+
+#endif                                           
/*SCIMBRIDGECLIENTKEYEVENTUTILITYGTK_H_*/
diff -Nru scim-1.4.18/extras/immodules/client-qt/im-scim-bridge-qt.cpp scim-
1.4.18+git20211204/extras/immodules/client-qt/im-scim-bridge-qt.cpp
--- scim-1.4.18/extras/immodules/client-qt/im-scim-bridge-qt.cpp        2017-
07-30 22:45:36.000000000 -0400
+++ scim-1.4.18+git20211204/extras/immodules/client-qt/im-scim-bridge-
qt.cpp  2021-12-04 05:40:01.000000000 -0500
@@ -19,14 +19,10 @@
 
 #include <cassert>
 
-#ifdef QT4
 #include <Qt>
-#include <QInputContextPlugin>
+#include <qpa/qplatforminputcontextplugin_p.h>
 
 using namespace Qt;
-#else
-#include <qinputcontextplugin.h>
-#endif
 
 #include "scim-bridge.h"
 #include "scim-bridge-client-common-qt.h"
@@ -37,8 +33,10 @@
 static ScimBridgeClientQt *client = NULL;
 
 /* The class Definition */
-class ScimBridgeInputContextPlugin: public QInputContextPlugin
+class ScimBridgeInputContextPlugin: public QPlatformInputContextPlugin
 {
+        Q_OBJECT
+        Q_PLUGIN_METADATA(IID QPlatformInputContextFactoryInterface_iid FILE
"scim.json")
 
     private:
 
@@ -59,7 +57,7 @@
 
         QString description (const QString &key);
         
-        QInputContext *create (const QString &key);
+        ScimBridgeClientIMContext *create (const QString &key, const
QStringList &param) Q_DECL_OVERRIDE;
 
         QString displayName (const QString &key);
 
@@ -69,7 +67,6 @@
 /* Implementations */
 QStringList ScimBridgeInputContextPlugin::scim_languages;
 
-
 ScimBridgeInputContextPlugin::ScimBridgeInputContextPlugin ()
 {
 }
@@ -107,13 +104,10 @@
 }
 
 
-QInputContext *ScimBridgeInputContextPlugin::create (const QString &key)
+ScimBridgeClientIMContext *ScimBridgeInputContextPlugin::create (const
QString &key, const QStringList &param)
 {
-#ifdef QT4
+    Q_UNUSED(param);
     if (key.toLower () != SCIM_BRIDGE_IDENTIFIER_NAME) {
-#else
-    if (key.lower () != SCIM_BRIDGE_IDENTIFIER_NAME) {
-#endif
         return NULL;
     } else {
         if (client == NULL) client = new ScimBridgeClientQt ();
@@ -127,8 +121,4 @@
     return key;
 }
 
-#ifdef QT4
-Q_EXPORT_PLUGIN2 (ScimBridgeInputContextPlugin, ScimBridgeInputContextPlugin)
-#else
-Q_EXPORT_PLUGIN (ScimBridgeInputContextPlugin)
-#endif
+#include "im-scim-bridge-qt.moc"
diff -Nru scim-1.4.18/extras/immodules/client-qt/.qmake.conf scim-
1.4.18+git20211204/extras/immodules/client-qt/.qmake.conf
--- scim-1.4.18/extras/immodules/client-qt/.qmake.conf  1969-12-31
19:00:00.000000000 -0500
+++ scim-1.4.18+git20211204/extras/immodules/client-qt/.qmake.conf      2021-
12-04 05:40:01.000000000 -0500
@@ -0,0 +1 @@
+load(qt_build_config)
diff -Nru scim-1.4.18/extras/immodules/client-qt/qt3/Makefile.am scim-
1.4.18+git20211204/extras/immodules/client-qt/qt3/Makefile.am
--- scim-1.4.18/extras/immodules/client-qt/qt3/Makefile.am      2017-07-30
22:45:36.000000000 -0400
+++ scim-1.4.18+git20211204/extras/immodules/client-qt/qt3/Makefile.am  1969-
12-31 19:00:00.000000000 -0500
@@ -1,64 +0,0 @@
-## Makefile.am -- Process this file with automake to produce Makefile.in
-##
-## Copyright (C) 2006 Ryo Dairiki
-##
-##
-## 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 and 
-## appearing in the file LICENSE.LGPL included in the package of this file.
-## You can also redistribute it and/or modify it under the terms of 
-## the GNU General Public License as published by the Free Software
Foundation and 
-## appearing in the file LICENSE.GPL included in the package of this file.
-##
-## 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.
-
-if SCIM_BUILD_QT3_IMMODULE
-
-AM_CPPFLAGS    = -I$(top_builddir) \
-                 -I$(top_srcdir) \
-                         -I$(top_srcdir)/extras/immodules/common \
-                         -I$(top_srcdir)/extras/immodules/client-common
-
-noinst_HEADERS = ../scim-bridge-client-qt.h ../scim-bridge-client-imcontext-
qt.h  ../scim-bridge-client-key-event-utility-qt.h ../scim-bridge-client-
common-qt.h
-
-moduledir = @QT3_IM_MODULEDIR@
-module_LTLIBRARIES = im-scim.la
-
-im_scim_la_SOURCES = ../im-scim-bridge-qt.cpp \
-                                                       ../scim-bridge-
client-qt.cpp \
-                                                       ../scim-bridge-
client-imcontext-qt.cpp \
-                                                       ../scim-bridge-
client-key-event-utility-qt.cpp \
-                                                       moc_scim-bridge-
client-qt.cpp
-
-im_scim_la_CXXFLAGS=@QT3_CFLAGS@ -DQT_IMMODULE
-im_scim_la_CFLAGS  =@QT3_CFLAGS@ -DQT_IMMODULE
-
-im_scim_la_LDFLAGS = -rpath $(moduledir) \
-                                                       -avoid-version -no-
undefined \
-                                                       -module \
-                                                       @QT3_LIBS@
-
-im_scim_la_LIBADD  =
$(top_builddir)/extras/immodules/common/libscimbridgecommon.la \
-
                                        
$(top_builddir)/extras/immodules/client-common/libscimbridgeclientcommon.la
-
-MOC = @QT3_MOC@
-
-moc_scim-bridge-client-qt.cpp: ../scim-bridge-client-qt.h
-       $(MOC) $< -o $@
-
-else
-
-moc_scim-bridge-client-qt.cpp:
-       touch $@
-
-endif
-
-dist-hook:
-       -rm -f $(distdir)/moc_scim-bridge-client-qt.cpp
-
-MAINTAINERCLEANFILES   = Makefile.in
-CLEANFILES = moc_scim-bridge-client-qt.cpp
-
diff -Nru scim-1.4.18/extras/immodules/client-qt/qt4/Makefile.am scim-
1.4.18+git20211204/extras/immodules/client-qt/qt4/Makefile.am
--- scim-1.4.18/extras/immodules/client-qt/qt4/Makefile.am      2017-07-30
22:45:36.000000000 -0400
+++ scim-1.4.18+git20211204/extras/immodules/client-qt/qt4/Makefile.am  1969-
12-31 19:00:00.000000000 -0500
@@ -1,64 +0,0 @@
-## Makefile.am -- Process this file with automake to produce Makefile.in
-##
-## Copyright (C) 2006 Ryo Dairiki
-##
-##
-## 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 and 
-## appearing in the file LICENSE.LGPL included in the package of this file.
-## You can also redistribute it and/or modify it under the terms of 
-## the GNU General Public License as published by the Free Software
Foundation and 
-## appearing in the file LICENSE.GPL included in the package of this file.
-##
-## 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.
-
-if SCIM_BUILD_QT4_IMMODULE
-
-AM_CPPFLAGS    = -I$(top_builddir) \
-                 -I$(top_srcdir) \
-                         -I$(top_srcdir)/extras/immodules/common \
-                         -I$(top_srcdir)/extras/immodules/client-common
-
-noinst_HEADERS = ../scim-bridge-client-qt.h ../scim-bridge-client-imcontext-
qt.h ../scim-bridge-client-key-event-utility-qt.h ../scim-bridge-client-
common-qt.h
-
-moduledir = @QT4_IM_MODULEDIR@
-module_LTLIBRARIES = im-scim.la
-
-im_scim_la_SOURCES = ../im-scim-bridge-qt.cpp \
-                                                       ../scim-bridge-
client-qt.cpp \
-                                                       ../scim-bridge-
client-imcontext-qt.cpp \
-                                                       ../scim-bridge-
client-key-event-utility-qt.cpp \
-                                                       moc_scim-bridge-
client-qt.cpp
-
-im_scim_la_CXXFLAGS=@QT4_CFLAGS@ -DQT_IMMODULE -DQT4 -g -O0
-im_scim_la_CFLAGS  =@QT4_CFLAGS@ -DQT_IMMODULE -DQT4 -g -O0
-
-im_scim_la_LDFLAGS = -rpath $(moduledir) \
-                                                       -avoid-version -no-
undefined \
-                                                       -module \
-                                                       @QT4_LIBS@
-
-im_scim_la_LIBADD  =
$(top_builddir)/extras/immodules/common/libscimbridgecommon.la \
-
                                        
$(top_builddir)/extras/immodules/client-common/libscimbridgeclientcommon.la
-
-MOC = @QT4_MOC@
-
-moc_scim-bridge-client-qt.cpp: ../scim-bridge-client-qt.h
-       $(MOC) $< -o $@
-
-else
-
-moc_scim-bridge-client-qt.cpp:
-       touch $@
-
-endif
-
-dist-hook:
-       -rm -f $(distdir)/moc_scim-bridge-client-qt.cpp
-
-MAINTAINERCLEANFILES   = Makefile.in
-CLEANFILES = moc_scim-bridge-client-qt.cpp
-
diff -Nru scim-1.4.18/extras/immodules/client-qt/README scim-
1.4.18+git20211204/extras/immodules/client-qt/README
--- scim-1.4.18/extras/immodules/client-qt/README       1969-12-31
19:00:00.000000000 -0500
+++ scim-1.4.18+git20211204/extras/immodules/client-qt/README   2021-12-04
05:40:01.000000000 -0500
@@ -0,0 +1,16 @@
+SCIM Qt5 Input Method Plugin
+
+This code is adopted from SCIM Qt4 counterpart, using the qmake build
+system.  Integration of qmake to autotools is possible in the future.
+
+To build and install,
+
+1. build scim, including the im-agent.
+2. change to this directory and call `qmake`
+3. make
+4. make install
+
+Reference:
+1. Debian packages gcin-qt5-immodule, uim-qt5-immodule
+   libfcitx-qt5-1 (dbus), ibus (dbus)
+2. https://www.kdab.com/qt-input-method-depth/
\ 文件尾没有换行符
diff -Nru scim-1.4.18/extras/immodules/client-qt/scim-bridge-client-common-
qt.h scim-1.4.18+git20211204/extras/immodules/client-qt/scim-bridge-client-
common-qt.h
--- scim-1.4.18/extras/immodules/client-qt/scim-bridge-client-common-
qt.h    2017-07-30 22:45:36.000000000 -0400
+++ scim-1.4.18+git20211204/extras/immodules/client-qt/scim-bridge-client-
common-qt.h     2021-12-04 05:40:01.000000000 -0500
@@ -27,13 +27,8 @@
 #ifndef SCIMBRIDGECOMMONQT_H_
 #define SCIMBRIDGECOMMONQT_H_
 
-#ifdef QT4
 #include <QString>
 #include <QStringList>
-#else
-#include <qstring.h>
-#include <qstringlist.h>
-#endif
 
 #include "scim-bridge.h"
 
diff -Nru scim-1.4.18/extras/immodules/client-qt/scim-bridge-client-imcontext-
qt.cpp scim-1.4.18+git20211204/extras/immodules/client-qt/scim-bridge-client-
imcontext-qt.cpp
--- scim-1.4.18/extras/immodules/client-qt/scim-bridge-client-imcontext-
qt.cpp  2017-07-30 22:45:36.000000000 -0400
+++ scim-1.4.18+git20211204/extras/immodules/client-qt/scim-bridge-client-
imcontext-qt.cpp        2021-12-04 05:40:01.000000000 -0500
@@ -20,16 +20,12 @@
 #include <cassert>
 #include <string>
 
-#ifdef QT4
 #include <QColor>
 #include <QInputMethodEvent>
 #include <QPalette>
 #include <QTextCharFormat>
 
-#ifdef Q_WS_X11
 #include <QX11Info>
-#endif
-#endif
 
 #include "scim-bridge-output.h"
 #include "scim-bridge-string.h"
@@ -39,13 +35,11 @@
 #include "scim-bridge-client-imcontext-qt.h"
 #include "scim-bridge-client-key-event-utility-qt.h"
 
-#ifdef QT4
 using namespace std;
 
 using namespace Qt;
 
 typedef QInputMethodEvent::Attribute QAttribute;
-#endif
 
 /* Static variables */
 class ScimBridgeClientIMContextImpl;
@@ -66,22 +60,16 @@
         bool x11FilterEvent (QWidget *widget, XEvent *event);
         bool filterEvent (const QEvent *event);
 
-#ifdef QT4
         void update ();
         QString identifierName ();
         QString language ();
 
-        void setFocusWidget (QWidget *widget);
+        bool isValid() const Q_DECL_OVERRIDE;
+        void setFocusObject (QObject *object) Q_DECL_OVERRIDE;
         void widgetDestroyed (QWidget *widget);
 
         bool isComposing () const;
         void mouseHandler (int offset, QMouseEvent *event);
-#else
-        void setFocus ();
-        void unsetFocus ();
-        void setMicroFocus (int x, int y, int w, int h, QFont *font = 0);
-        void mouseHandler (int offset, QEvent::Type type, ButtonState button,
ButtonState state);
-#endif
 
         void reset ();
 
@@ -103,11 +91,9 @@
         scim_bridge_imcontext_id_t get_id () const;
         void set_id (scim_bridge_imcontext_id_t new_id);
 
-#ifdef QT4
         bool get_surrounding_text (unsigned int before_max, unsigned int
after_max, char **string, int *cursor_position);
         bool delete_surrounding_text (int offset, int length);
         bool replace_surrounding_text (const char *text, int
cursor_position);
-#endif
 
     private:
 
@@ -117,12 +103,7 @@
 
         QString preedit_string;
 
-#ifdef QT4
         QList<QAttribute> preedit_attributes;
-#else
-        int preedit_selected_offset;
-        int preedit_selected_length;
-#endif
 
         int preedit_cursor_position;
 
@@ -165,12 +146,7 @@
 {
     scim_bridge_pdebugln (5,
"ScimBridgeClientIMContextImpl::ScimBridgeClientIMContextImpl ()");
 
-#ifdef QT4
     preedit_attributes.push_back (QAttribute (QInputMethodEvent::Cursor,
preedit_cursor_position, true, 0));
-#else
-    preedit_selected_offset = 0;
-    preedit_selected_length = 0;
-#endif
 
     if (!scim_bridge_client_is_messenger_opened ()) {
         scim_bridge_perrorln ("The messenger is now down");
@@ -197,8 +173,6 @@
     }
 }
 
-#ifdef QT4
-
 QString ScimBridgeClientIMContextImpl::identifierName ()
 {
     return SCIM_BRIDGE_IDENTIFIER_NAME;
@@ -216,16 +190,20 @@
     update ();
 }
 
-void ScimBridgeClientIMContextImpl::setFocusWidget (QWidget *widget)
+bool ScimBridgeClientIMContextImpl::isValid() const
 {
-    scim_bridge_pdebugln (4, "ScimBridgeClientIMContextImpl::setFocusWidget
()");
-    QInputContext::setFocusWidget (widget);
-       if (widget == NULL) {
-       focus_out ();
-       }
-       else {
-       focus_in ();
-       }
+    return true;
+}
+
+void ScimBridgeClientIMContextImpl::setFocusObject (QObject *object)
+{
+    scim_bridge_pdebugln (4, "ScimBridgeClientIMContextImpl::setFocusObject
()");
+    QPlatformInputContext::setFocusObject (object);
+    if (object == NULL) {
+        focus_out ();
+    } else {
+        focus_in ();
+    }
     update ();
 }
 
@@ -276,43 +254,10 @@
     return false;
 }
 
-#else
-
-void ScimBridgeClientIMContextImpl::setFocus ()
-{
-    scim_bridge_pdebugln (4, "ScimBridgeClientIMContextImpl::setFocus ()");
-    
-    focus_in ();
-}
-
-
-void ScimBridgeClientIMContextImpl::unsetFocus ()
-{
-    scim_bridge_pdebugln (4, "ScimBridgeClientIMContextImpl::unsetFocus ()");
-    
-    focus_out ();
-}
-
-
-void ScimBridgeClientIMContextImpl::setMicroFocus (int x, int y, int w, int
h, QFont *qfont)
-{
-    scim_bridge_pdebugln (4, "ScimBridgeClientIMContextImpl::setMicroFocus
()");
-
-    QPoint new_cursor_location (x, y + h);
-    set_cursor_location (new_cursor_location);
-}
-
-void ScimBridgeClientIMContextImpl::mouseHandler (int offset, QEvent::Type
type, ButtonState button, ButtonState state)
-{
-}
-#endif
-
-
 bool ScimBridgeClientIMContextImpl::x11FilterEvent (QWidget *widget, XEvent
*xevent)
 {
     scim_bridge_pdebugln (5, "ScimBridgeClientIMContextImpl::x11FilterEvent
()");
 
-#ifdef Q_WS_X11
     if (key_event_forwarded || (xevent->type != XKeyPress && xevent->type !=
XKeyRelease)) return false;
     
     if (focused_imcontext != this) focus_in ();
@@ -331,17 +276,14 @@
             return consumed;
         }
     }
-#endif
 
     return false;
 }
 
-
 bool ScimBridgeClientIMContextImpl::filterEvent (const QEvent *qevent)
 {
     scim_bridge_pdebugln (5, "ScimBridgeClientIMContextImpl::filterEvent
()");
 
-#ifndef Q_WS_X11
     if (key_event_forwarded || (qevent->type () != QEvent::KeyPress &&
qevent->type () != QEvent::KeyRelease)) return false;
     
     if (focused_imcontext != this) focus_in ();
@@ -364,7 +306,6 @@
             return consumed;
         }
     }
-#endif
 
     return false;
 }
@@ -375,13 +316,8 @@
     scim_bridge_pdebugln (5, "ScimBridgeClientIMContextImpl::reset ()");
 
     preedit_cursor_position = 0;
-#ifdef QT4
     preedit_attributes.clear ();
     preedit_attributes.push_back (QAttribute (QInputMethodEvent::Cursor,
preedit_cursor_position, true, 0));
-#else
-    preedit_selected_offset = 0;
-    preedit_selected_length = 0;
-#endif
     preedit_string = "";
 
     if (scim_bridge_client_is_messenger_opened ()) {
@@ -389,10 +325,6 @@
             scim_bridge_perrorln ("An IOException at filterEvent ()");
         }
     }
-
-#ifndef QT4
-    QInputContext::reset ();
-#endif
 }
 
 
@@ -469,20 +401,16 @@
     scim_bridge_pdebugln (5, "ScimBridgeClientIMContextImpl::commit ()");
     
     if (commit_string.length () <= 0) return;
-#ifdef QT4
     scim_bridge_pdebugln (9, "commit string: %s", commit_string.toUtf8
().data ());
-#endif
+
+    QObject *input = qApp->focusObject();
+    if (!input) return;
 
     const bool is_composing = isComposing ();
 
-#ifdef QT4
     QInputMethodEvent commit_event;
     commit_event.setCommitString (commit_string);
-    sendEvent (commit_event);
-#else
-    if (!is_composing) sendIMEvent (QEvent::IMStart);
-    sendIMEvent (QEvent::IMEnd, commit_string);
-#endif
+    QCoreApplication::sendEvent (input, &commit_event);
 
     if (is_composing) update_preedit ();
 }
@@ -495,21 +423,9 @@
     QWidget *focused_widget = qApp->focusWidget ();
     if (focused_widget != NULL) {
         key_event_forwarded = true;
-#ifdef Q_WS_X11
-        const WId window_id = focused_widget->winId ();
-#ifdef QT4
-        Display *x11_display = QX11Info::display();
-#else
-        Display *x11_display = qt_xdisplay ();
-#endif
-        XEvent *x_event = scim_bridge_key_event_bridge_to_x11 (key_event,
x11_display, window_id);
-        qApp->x11ProcessEvent (x_event);
-        free (x_event);
-#else
         QKeyEvent *forwarded_key_event = scim_bridge_key_event_bridge_to_qt
(key_event);
         QApplication::sendEvent (focused_widget, forwarded_key_event);
         delete forwarded_key_event;
-#endif
         key_event_forwarded = false;
     } else {
         scim_bridge_pdebugln (4, "No widget is focused");
@@ -525,13 +441,8 @@
     if (!preedit_shown) {
         preedit_string = "";
         preedit_cursor_position = 0;
-#ifdef QT4
         preedit_attributes.clear ();
         preedit_attributes.push_back (QAttribute (QInputMethodEvent::Cursor,
preedit_cursor_position, true, 0));
-#else
-        preedit_selected_offset = 0;
-        preedit_selected_length = 0;
-#endif
     }
 }
 
@@ -554,13 +465,8 @@
 {
     scim_bridge_pdebugln (5,
"ScimBridgeClientIMContextImpl::set_preedit_attribute ()");
     
-#ifdef QT4
     preedit_attributes.clear ();
     preedit_attributes.push_back (QAttribute (QInputMethodEvent::Cursor,
preedit_cursor_position, true, 0));
-#else
-    preedit_selected_offset = 0;
-    preedit_selected_length = 0;
-#endif
 
     for (int i = 0; i < attribute_count; ++i) {
         const ScimBridgeAttribute *attribute = attributes[i];
@@ -570,7 +476,6 @@
         const scim_bridge_attribute_type_t attribute_type =
scim_bridge_attribute_get_type (attribute);
         const scim_bridge_attribute_value_t attribute_value =
scim_bridge_attribute_get_value (attribute);
 
-#ifdef QT4
         const size_t attribute_length = attribute_end - attribute_begin;
 
         const QWidget *focused_widget = qApp->focusWidget ();
@@ -637,13 +542,6 @@
         default:
             break;
         }
-#else
-        if (attribute_type == ATTRIBUTE_DECORATE && (attribute_value ==
SCIM_BRIDGE_ATTRIBUTE_DECORATE_HIGHLIGHT || attribute_value ==
SCIM_BRIDGE_ATTRIBUTE_DECORATE_REVERSE)) {
-            preedit_selected_offset = attribute_begin;
-            preedit_selected_length = attribute_end - attribute_begin;
-            break;
-        }
-#endif
     }
 }
 
@@ -652,26 +550,13 @@
 {
     scim_bridge_pdebugln (5, "ScimBridgeClientIMContextImpl::update_preedit
()");
 
-#ifdef QT4
+    QObject *input = qApp->focusObject();
+    if (!input) return;
+
     preedit_attributes[0] = QAttribute (QInputMethodEvent::Cursor,
preedit_cursor_position, true, 0);
     QInputMethodEvent im_event (preedit_string, preedit_attributes);
-    sendEvent (im_event);
+    QCoreApplication::sendEvent(input, &im_event);
     update ();
-#else
-    if (preedit_shown) {
-        if (!isComposing ()) sendIMEvent (QEvent::IMStart);
-        const size_t preedit_length = preedit_string.length ();
-
-        size_t cursor_position = preedit_cursor_position;
-        if (cursor_position > preedit_length) cursor_position =
preedit_length;
-
-        size_t selected_length = preedit_selected_length;
-        if (cursor_position + selected_length > preedit_length)
selected_length = preedit_length - cursor_position;
-        sendIMEvent (QEvent::IMCompose, preedit_string, cursor_position,
selected_length);
-    } else {
-        if (isComposing ()) sendIMEvent (QEvent::IMEnd);
-    }
-#endif
 }
 
 
@@ -780,37 +665,22 @@
 
 boolean scim_bridge_client_imcontext_get_surrounding_text
(ScimBridgeClientIMContext *imcontext, int before_max, int after_max, char
**string, int *cursor_position)
 {
-#ifdef QT4
     ScimBridgeClientIMContextImpl *imcontext_impl =
static_cast<ScimBridgeClientIMContextImpl*> (imcontext);
     return imcontext_impl->get_surrounding_text (before_max, after_max,
string, cursor_position);
-#else
-    scim_bridge_perrorln ("FIXME:
scim_bridge_client_imcontext_get_surrounding_text () is not yet
implemented.");
-    return FALSE;
-#endif
 }
 
 
 boolean scim_bridge_client_imcontext_delete_surrounding_text
(ScimBridgeClientIMContext *imcontext, int offset, int length)
 {
-#ifdef QT4
     ScimBridgeClientIMContextImpl *imcontext_impl =
static_cast<ScimBridgeClientIMContextImpl*> (imcontext);
     return imcontext_impl->delete_surrounding_text (offset, length);
-#else
-    scim_bridge_perrorln ("FIXME:
scim_bridge_client_imcontext_delete_surrounding_text () is not yet
implemented.");
-    return FALSE;
-#endif
 }
 
 
 boolean scim_bridge_client_imcontext_replace_surrounding_text
(ScimBridgeClientIMContext *imcontext, int cursor_position, const char
*string)
 {
-#ifdef QT4
     ScimBridgeClientIMContextImpl *imcontext_impl =
static_cast<ScimBridgeClientIMContextImpl*> (imcontext);
     return imcontext_impl->replace_surrounding_text (string,
cursor_position);
-#else
-    scim_bridge_perrorln ("FIXME:
scim_bridge_client_imcontext_replace_surrounding_text () is not yet
implemented.");
-    return FALSE;
-#endif
 }
 
 
diff -Nru scim-1.4.18/extras/immodules/client-qt/scim-bridge-client-imcontext-
qt.h scim-1.4.18+git20211204/extras/immodules/client-qt/scim-bridge-client-
imcontext-qt.h
--- scim-1.4.18/extras/immodules/client-qt/scim-bridge-client-imcontext-
qt.h    2017-07-30 22:45:36.000000000 -0400
+++ scim-1.4.18+git20211204/extras/immodules/client-qt/scim-bridge-client-
imcontext-qt.h  2021-12-04 05:40:01.000000000 -0500
@@ -26,25 +26,14 @@
 #ifndef SCIMBRIDGECLIENTIMCONTEXTQT_H_
 #define SCIMBRIDGECLIENTIMCONTEXTQT_H_
 
-#ifdef QT4
 #include <QApplication>
 #include <QEvent>
 #include <QFont>
-#include <QInputContext>
+#include <qpa/qplatforminputcontext.h>
 #include <QInputMethodEvent>
 #include <QObject>
 #include <QPoint>
 #include <QWidget>
-#else
-#include <qapplication.h>
-#include <qevent.h>
-#include <qfont.h>
-#include <qinputcontext.h>
-#include <qobject.h>
-#include <qptrlist.h>
-#include <qpoint.h>
-#include <qwidget.h>
-#endif
 
 #include "scim-bridge.h"
 #include "scim-bridge-attribute.h"
@@ -56,7 +45,7 @@
 /**
  * IMContext class for qt client.
  */
-struct _ScimBridgeClientIMContext: public QInputContext
+struct _ScimBridgeClientIMContext: public QPlatformInputContext
 {
 
     public:
@@ -94,15 +83,6 @@
         virtual ~_ScimBridgeClientIMContext () {}
 
         /**
-         * Filter a event from X11.
-         *
-         * @param widget The widget.
-         * @param A event from X11.
-         * @return If this event is consumed or not.
-         */
-        virtual bool x11FilterEvent (QWidget *widget, XEvent *event) = 0;
-
-        /**
          * Filter a key event.
          *
          * @param event The key event.
@@ -110,7 +90,6 @@
          */
         virtual bool filterEvent (const QEvent *event) = 0;
 
-#ifdef QT4
         /**
          * The focus has been changed.
          */
@@ -145,41 +124,6 @@
          */
         virtual void widgetDestroyed (QWidget *widget) = 0;
 
-#else
-
-        /**
-         * Focus an IMContext.
-         */
-        virtual void setFocus () = 0;
-
-        /**
-         * Unfocus an IMContext.
-         */
-        virtual void unsetFocus () = 0;
-        
-        /**
-         * Set the focused area in the display.
-         *
-         * @param x The X loation of the focused area.
-         * @param y The Y loation of the focused area.
-         * @param w The width of the focused area.
-         * @param h The height of the focused area.
-         * @param font The font.
-         */
-        virtual void setMicroFocus (int x, int y, int w, int h, QFont *font =
0) = 0;
-
-        /**
-         * Filter a mouse event.
-         *
-         * @param offset The cursor offset in the preedit string.
-         * @param type The type of the event.
-         * @param button The button of this event.
-         * @param state The state of the button.
-         */
-        virtual void mouseHandler (int offset, QEvent::Type type, ButtonState
button, ButtonState state) = 0;
-
-#endif
-
         /**
          * Reset the current IME.
          */
diff -Nru scim-1.4.18/extras/immodules/client-qt/scim-bridge-client-key-event-
utility-qt.cpp scim-1.4.18+git20211204/extras/immodules/client-qt/scim-bridge-
client-key-event-utility-qt.cpp
--- scim-1.4.18/extras/immodules/client-qt/scim-bridge-client-key-event-
utility-qt.cpp  2017-07-30 22:45:36.000000000 -0400
+++ scim-1.4.18+git20211204/extras/immodules/client-qt/scim-bridge-client-key-
event-utility-qt.cpp    2021-12-04 05:40:01.000000000 -0500
@@ -22,15 +22,10 @@
 #include <cstdlib>
 #include <map>
 
-#ifdef QT4
 #include <QApplication>
 #include <QChar>
 #include <QEvent>
 #include <QKeyEvent>
-#else
-#include <qapplication.h>
-#include <qkeycode.h>
-#endif
 
 #include "scim-bridge-output.h"
 #include "scim-bridge-client-key-event-utility-qt.h"
@@ -82,13 +77,8 @@
     register_key (Qt::Key_Up, SCIM_BRIDGE_KEY_CODE_Up);
     register_key (Qt::Key_Right, SCIM_BRIDGE_KEY_CODE_Right);
     register_key (Qt::Key_Down, SCIM_BRIDGE_KEY_CODE_Down);
-#ifdef QT4
     register_key (Qt::Key_PageUp, SCIM_BRIDGE_KEY_CODE_Prior);
-    register_key (Qt::Key_PageUp, SCIM_BRIDGE_KEY_CODE_Next);
-#else
-    register_key (Qt::Key_Prior, SCIM_BRIDGE_KEY_CODE_Prior);
-    register_key (Qt::Key_Next, SCIM_BRIDGE_KEY_CODE_Next);
-#endif
+    register_key (Qt::Key_PageDown, SCIM_BRIDGE_KEY_CODE_Next);
     register_key (Qt::Key_CapsLock, SCIM_BRIDGE_KEY_CODE_Caps_Lock);
     register_key (Qt::Key_NumLock, SCIM_BRIDGE_KEY_CODE_Num_Lock);
     register_key (Qt::Key_ScrollLock, SCIM_BRIDGE_KEY_CODE_Scroll_Lock);
@@ -184,34 +174,17 @@
     if (bridge_key_code < 0x1000) {
         if (bridge_key_code >= SCIM_BRIDGE_KEY_CODE_a && bridge_key_code <=
SCIM_BRIDGE_KEY_CODE_z) {
             ascii_code = bridge_key_code;
-#ifdef QT4
-            qt_key_code = QChar (ascii_code).toUpper ().toAscii ();
-#else
-            qt_key_code = QChar (ascii_code).upper ();
-#endif
+            qt_key_code = QChar (ascii_code).toUpper ().toLatin1 ();
         } else {
             ascii_code = bridge_key_code;
             qt_key_code = bridge_key_code;
         }
     } else if (bridge_key_code < 0x3000) {
-#ifdef Q_WS_WIN
         qt_key_code = bridge_key_code;
     } else {
-        qt_key_code = Key_unknown;
+        qt_key_code = Qt::Key_unknown;
     }
-#else
-        qt_key_code = bridge_key_code | Qt::UNICODE_ACCEL;
-    } else {
-        map<scim_bridge_key_code_t, int>::iterator iter =
bridge_to_qt_key_map.find (bridge_key_code);
-        if (iter != bridge_to_qt_key_map.end ()) {
-            qt_key_code = iter->second;
-        } else {
-            qt_key_code = Qt::Key_unknown;
-        }
-    }
-#endif
 
-#ifdef QT4
     Qt::KeyboardModifiers modifiers = Qt::NoModifier;
 
     if (scim_bridge_key_event_is_alt_down (bridge_key_event)) modifiers |=
Qt::AltModifier;
@@ -220,16 +193,6 @@
     if (scim_bridge_key_event_is_meta_down (bridge_key_event)) modifiers |=
Qt::MetaModifier;
 
     return new QKeyEvent (type, qt_key_code, modifiers);
-#else
-    unsigned int modifiers = 0;
-
-    if (scim_bridge_key_event_is_alt_down (bridge_key_event)) modifiers |=
Qt::AltButton;
-    if (scim_bridge_key_event_is_shift_down (bridge_key_event)) modifiers |=
Qt::ShiftButton;
-    if (scim_bridge_key_event_is_control_down (bridge_key_event)) modifiers
|= Qt::ControlButton;
-    if (scim_bridge_key_event_is_meta_down (bridge_key_event)) modifiers |=
Qt::MetaButton;
-
-    return new QKeyEvent (type, qt_key_code, ascii_code, modifiers);
-#endif
 }
 
 
@@ -239,7 +202,6 @@
     
     ScimBridgeKeyEvent *bridge_key_event = scim_bridge_alloc_key_event ();
 
-#ifdef QT4
     const Qt::KeyboardModifiers modifiers = key_event->modifiers ();
 
     if (modifiers & Qt::ShiftModifier) {
@@ -254,22 +216,6 @@
     if (modifiers & Qt::MetaModifier) {
         scim_bridge_key_event_set_meta_down (bridge_key_event, TRUE);
     }
-#else
-    const int modifiers = key_event->state ();
-
-    if (modifiers & Qt::ShiftButton) {
-        scim_bridge_key_event_set_shift_down (bridge_key_event, TRUE);
-    }
-    if (modifiers & Qt::ControlButton) {
-        scim_bridge_key_event_set_control_down (bridge_key_event, TRUE);
-    }
-    if (modifiers & Qt::AltButton) {
-        scim_bridge_key_event_set_alt_down (bridge_key_event, TRUE);
-    }
-    if (modifiers & Qt::MetaButton) {
-        scim_bridge_key_event_set_meta_down (bridge_key_event, TRUE);
-    }
-#endif
 
     const int qt_key_code = key_event->key ();
     int bridge_key_code;
@@ -294,17 +240,9 @@
         }
         
         if (!scim_bridge_key_event_is_caps_lock_down (bridge_key_event) ^
scim_bridge_key_event_is_shift_down (bridge_key_event)) {
-#ifdef QT4
                bridge_key_code = QChar (qt_key_code).toLower ().unicode ();
-#else
-               bridge_key_code = QChar (qt_key_code).lower ().unicode ();
-#endif
            } else {
-#ifdef QT4
                bridge_key_code = QChar (qt_key_code).toUpper ().unicode ();
-#else
-               bridge_key_code = QChar (qt_key_code).upper ().unicode ();
-#endif
            }
     } else {
         map<int, scim_bridge_key_code_t>::iterator iter =
qt_to_bridge_key_map.find (qt_key_code);
@@ -324,7 +262,6 @@
 }
 
 
-#ifdef Q_WS_X11
 XEvent *scim_bridge_key_event_bridge_to_x11 (const ScimBridgeKeyEvent
*bridge_key_event, Display *display, WId window_id)
 {
     XEvent *x_event = static_cast<XEvent*> (malloc (sizeof (XEvent)));
@@ -412,5 +349,3 @@
     
     return bridge_key_event;
 }
-
-#endif
diff -Nru scim-1.4.18/extras/immodules/client-qt/scim-bridge-client-key-event-
utility-qt.h scim-1.4.18+git20211204/extras/immodules/client-qt/scim-bridge-
client-key-event-utility-qt.h
--- scim-1.4.18/extras/immodules/client-qt/scim-bridge-client-key-event-
utility-qt.h    2017-07-30 22:45:36.000000000 -0400
+++ scim-1.4.18+git20211204/extras/immodules/client-qt/scim-bridge-client-key-
event-utility-qt.h      2021-12-04 05:40:01.000000000 -0500
@@ -32,7 +32,6 @@
 
 #include "scim-bridge-client-common-qt.h"
 
-#ifdef Q_WS_X11
 #include <X11/Xlib.h>
 #include <X11/keysym.h>
 #include <X11/Xutil.h>
@@ -40,7 +39,6 @@
 static const int XKeyRelease = KeyRelease;
 #undef KeyPress
 #undef KeyRelease
-#endif
 
 class QKeyEvent;
 
@@ -60,7 +58,6 @@
  */
 ScimBridgeKeyEvent *scim_bridge_key_event_qt_to_bridge (const QKeyEvent
*qt_key_event);
 
-#ifdef Q_WS_X11
 /**
  * Translate a key event from scim-bridge into X11.
  *
@@ -79,6 +76,5 @@
  * @return The key event from scim-bridge.
  */
 ScimBridgeKeyEvent* scim_bridge_key_event_x11_to_bridge (const XEvent
*x11_event);
-#endif
 
 #endif                                           
/*SCIMBRIDGECLIENTKEYEVENTUTILITYQT_H_*/
diff -Nru scim-1.4.18/extras/immodules/client-qt/scim-bridge-client-qt.cpp
scim-1.4.18+git20211204/extras/immodules/client-qt/scim-bridge-client-qt.cpp
--- scim-1.4.18/extras/immodules/client-qt/scim-bridge-client-qt.cpp    2017-
07-30 22:45:36.000000000 -0400
+++ scim-1.4.18+git20211204/extras/immodules/client-qt/scim-bridge-client-
qt.cpp  2021-12-04 05:40:01.000000000 -0500
@@ -23,9 +23,7 @@
 
 #include "scim-bridge-client-qt.h"
 
-#ifdef QT4
 using namespace Qt;
-#endif
 
 /* Static variables */
 static ScimBridgeClientQt *client = NULL;
diff -Nru scim-1.4.18/extras/immodules/client-qt/scim-bridge-client-qt.h scim-
1.4.18+git20211204/extras/immodules/client-qt/scim-bridge-client-qt.h
--- scim-1.4.18/extras/immodules/client-qt/scim-bridge-client-qt.h      2017-
07-30 22:45:36.000000000 -0400
+++ scim-1.4.18+git20211204/extras/immodules/client-qt/scim-bridge-client-
qt.h    2021-12-04 05:40:01.000000000 -0500
@@ -26,13 +26,8 @@
 #ifndef SCIMBRIDGECLIENTQT_H_
 #define SCIMBRIDGECLIENTQT_H_
 
-#ifdef QT4
 #include <QObject>
 #include <QSocketNotifier>
-#else
-#include <qobject.h>
-#include <qsocketnotifier.h>
-#endif
 
 #include "scim-bridge.h"
 #include "scim-bridge-client-imcontext-qt.h"
diff -Nru scim-1.4.18/extras/immodules/client-qt/scim.json scim-
1.4.18+git20211204/extras/immodules/client-qt/scim.json
--- scim-1.4.18/extras/immodules/client-qt/scim.json    1969-12-31
19:00:00.000000000 -0500
+++ scim-1.4.18+git20211204/extras/immodules/client-qt/scim.json        2021-
12-04 05:40:01.000000000 -0500
@@ -0,0 +1,3 @@
+{
+    "Keys": [ "scim" ]
+}
diff -Nru scim-1.4.18/extras/immodules/client-qt/scim.pro scim-
1.4.18+git20211204/extras/immodules/client-qt/scim.pro
--- scim-1.4.18/extras/immodules/client-qt/scim.pro     1969-12-31
19:00:00.000000000 -0500
+++ scim-1.4.18+git20211204/extras/immodules/client-qt/scim.pro 2021-12-04
05:40:01.000000000 -0500
@@ -0,0 +1,25 @@
+CONFIG += plugin
+TARGET = im-scim
+INCLUDEPATH += . ../common ../client-common
+QT += gui-private widgets x11extras
+
+HEADERS += scim-bridge-client-common-qt.h \
+           scim-bridge-client-imcontext-qt.h \
+           scim-bridge-client-key-event-utility-qt.h \
+           scim-bridge-client-qt.h
+
+SOURCES += im-scim-bridge-qt.cpp \
+           scim-bridge-client-imcontext-qt.cpp \
+           scim-bridge-client-key-event-utility-qt.cpp \
+           scim-bridge-client-qt.cpp
+
+QMAKE_LIBDIR += ../client-common/.libs ../common/.libs
+LIBS += -lscimbridgeclientcommon -lscimbridgecommon -lX11
+
+OTHER_FILES += scim.json
+
+PLUGIN_TYPE = platforminputcontexts
+PLUGIN_EXTENDS = -
+PLUGIN_CLASS_NAME = ScimBridgeInputContextPlugin
+target.path += $$[QT_INSTALL_PLUGINS]/platforminputcontexts
+load(qt_plugin)
diff -Nru scim-1.4.18/extras/immodules/configure.ac scim-
1.4.18+git20211204/extras/immodules/configure.ac
--- scim-1.4.18/extras/immodules/configure.ac   2017-07-30 22:45:36.000000000
-0400
+++ scim-1.4.18+git20211204/extras/immodules/configure.ac       2021-12-04
05:40:01.000000000 -0500
@@ -65,6 +65,10 @@
                        [SCIM_BRIDGE_HAS_GTK3=yes],
                        [SCIM_BRIDGE_HAS_GTK3=no])
 
+PKG_CHECK_MODULES(GTK4, [gtk4 >= 4.0.0 pango >= 1.48.0 gdk-pixbuf-2.0 >=
2.42.0],
+                       [SCIM_BRIDGE_HAS_GTK4=yes],
+                       [SCIM_BRIDGE_HAS_GTK4=no])
+
 SCIM_BRIDGE_HAS_GTK2_2=no
 if test "$SCIM_BRIDGE_HAS_GTK2" = "yes"; then
   if $PKG_CONFIG --exists "gtk+-2.0 >= 2.2" ; then
@@ -98,6 +102,17 @@
   AC_SUBST(GTK3_BINARY_VERSION)
 fi
 
+if test "$SCIM_BRIDGE_HAS_GTK4" = "yes"; then
+  GTK4_BINARY_VERSION=`$PKG_CONFIG --variable=gtk_binary_version gtk4`
+  GTK4_LIBDIR=`$PKG_CONFIG --variable=libdir gtk4`
+  if test -z "$GTK4_LIBDIR)"; then
+    GTK4_LIBDIR="$libdir"
+  fi
+  AC_SUBST(GTK4_LIBDIR)
+  AC_SUBST(GTK4_VERSION)
+  AC_SUBST(GTK4_BINARY_VERSION)
+fi
+
 # Check if we should build scim-bridge-qt-immodule
 PKG_CHECK_MODULES(QT3, [qt-mt >= 3.3],
                        [SCIM_BRIDGE_HAS_QT3=yes],
@@ -162,6 +177,10 @@
              [AS_HELP_STRING([--enable-gtk3-immodule], [build GTK3 IM
module])], , 
                  enable_gtk3_immodule=yes)
 
+AC_ARG_ENABLE(gtk4-immodule,
+             [AS_HELP_STRING([--enable-gtk4-immodule], [build GTK4 IM
module])], , 
+                 enable_gtk4_immodule=yes)
+
 AC_ARG_ENABLE(qt3-immodule,
              [AS_HELP_STRING([--enable-qt3-immodule], [build Qt3 IM
module])], , 
                  enable_qt3_immodule=yes)
@@ -224,6 +243,15 @@
   enable_gtk3_immodule=no
 fi
 
+if test "$enable_gtk4_immodule" = "yes" -a "$SCIM_BRIDGE_HAS_GTK4" = "yes";
then
+  SCIM_BRIDGE_BUILD_GTK4_IMMODULE=1
+  SCIM_BRIDGE_BUILD_IMMODULE=1
+  enable_immodule=yes
+else
+  SCIM_BRIDGE_BUILD_GTK4_IMMODULE=0
+  enable_gtk4_immodule=no
+fi
+
 if test "$enable_qt3_immodule" = "yes" -a "$SCIM_BRIDGE_HAS_QT3" = "yes";
then
   SCIM_BRIDGE_BUILD_QT3_IMMODULE=1
   SCIM_BRIDGE_BUILD_IMMODULE=1
@@ -269,6 +297,9 @@
 AM_CONDITIONAL(SCIM_BRIDGE_BUILD_GTK3_IMMODULE,
                [test "$enable_gtk3_immodule" = "yes"])
 
+AM_CONDITIONAL(SCIM_BRIDGE_BUILD_GTK4_IMMODULE,
+               [test "$enable_gtk4_immodule" = "yes"])
+
 AM_CONDITIONAL(SCIM_BRIDGE_BUILD_QT3_IMMODULE,
                [test "$enable_qt3_immodule" = "yes"])
 
@@ -285,6 +316,7 @@
 AC_SUBST(SCIM_BRIDGE_BUILD_AGENT)
 AC_SUBST(SCIM_BRIDGE_BUILD_GTK2_IMMODULE)
 AC_SUBST(SCIM_BRIDGE_BUILD_GTK3_IMMODULE)
+AC_SUBST(SCIM_BRIDGE_BUILD_GTK4_IMMODULE)
 AC_SUBST(SCIM_BRIDGE_BUILD_QT3_IMMODULE)
 AC_SUBST(SCIM_BRIDGE_BUILD_QT4_IMMODULE)
 AC_SUBST(SCIM_BRIDGE_BUILD_CLUTTER_IMMODULE)
@@ -343,6 +375,7 @@
   Build Agent              $enable_agent
   Build GTK2 IMModule      $enable_gtk2_immodule
   Build GTK3 IMModule      $enable_gtk3_immodule
+  Build GTK4 IMModule      $enable_gtk4_immodule
   Build QT3 IMModule       $enable_qt3_immodule
   Build QT4 IMModule       $enable_qt4_immodule
   Build CLUTTER IMModule   $enable_clutter_immodule
diff -Nru scim-1.4.18/extras/immodules/Makefile.am scim-
1.4.18+git20211204/extras/immodules/Makefile.am
--- scim-1.4.18/extras/immodules/Makefile.am    2017-07-30 22:45:36.000000000
-0400
+++ scim-1.4.18+git20211204/extras/immodules/Makefile.am        2021-12-04
05:40:01.000000000 -0500
@@ -37,4 +37,4 @@
 MAINTAINERCLEANFILES    = Makefile.in
 CLEANFILES      = *.bak
 
-SUBDIRS = common client-common client-gtk/gtk2 client-gtk/gtk3 client-qt/qt3
client-qt/qt4 client-clutter agent doc
+SUBDIRS = common client-common client-gtk/gtk2 client-gtk/gtk3 client-
gtk/gtk4 client-clutter agent doc

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to