Convert immodules to use an extension point

Add an extension point called gtk-im-module, which requires
the type GtkIMContext. Simplify the loading by using GIO
infrastructure. Drop the locale filtering for now, I don't
think it is really necessary nowadays.

Convert existing platform modules to gio modules.
Sill to do: Drop the conditional build machinery.
Either always include them, or never.
This commit is contained in:
Matthias Clasen 2018-02-19 18:29:00 -05:00
parent e6bf832514
commit 29bcc38ae6
20 changed files with 305 additions and 1482 deletions

View File

@ -15,9 +15,4 @@ if [ -z "$DESTDIR" ]; then
echo Updating icon cache...
gtk-update-icon-cache -q -t -f ${gtk_datadir}/icons/hicolor
echo Updating input method modules cache...
gtk_imdir=${gtk_libdir}/gtk-${gtk_api_version}/${gtk_abi_version}
mkdir -p ${gtk_imdir}
gtk4-query-immodules > ${gtk_imdir}/immodules.cache
fi

View File

@ -125,7 +125,6 @@
#include <gtk/gtkiconview.h>
#include <gtk/gtkimage.h>
#include <gtk/gtkimcontext.h>
#include <gtk/gtkimcontextinfo.h>
#include <gtk/gtkimcontextsimple.h>
#include <gtk/gtkimmulticontext.h>
#include <gtk/gtkinfobar.h>

View File

@ -1,44 +0,0 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2000 Red Hat Software
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GTK_IM_CONTEXT_INFO_H__
#define __GTK_IM_CONTEXT_INFO_H__
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk.h> can be included directly."
#endif
#include <glib.h>
G_BEGIN_DECLS
typedef struct _GtkIMContextInfo GtkIMContextInfo;
struct _GtkIMContextInfo
{
const gchar *context_id;
const gchar *context_name;
const gchar *domain;
const gchar *domain_dirname;
const gchar *default_locales;
};
G_END_DECLS
#endif /* __GTK_IM_CONTEXT_INFO_H__ */

View File

@ -40,6 +40,7 @@
#include "gtkdebug.h"
#include "gtkintl.h"
#include "gtkcomposetable.h"
#include "gtkimmodule.h"
#include "gtkimcontextsimpleprivate.h"
#include "gtkimcontextsimpleseqs.h"
@ -164,7 +165,12 @@ static void gtk_im_context_simple_get_preedit_string (GtkIMContext
static void gtk_im_context_simple_set_client_widget (GtkIMContext *context,
GtkWidget *widget);
G_DEFINE_TYPE_WITH_PRIVATE (GtkIMContextSimple, gtk_im_context_simple, GTK_TYPE_IM_CONTEXT)
G_DEFINE_TYPE_WITH_CODE (GtkIMContextSimple, gtk_im_context_simple, GTK_TYPE_IM_CONTEXT,
G_ADD_PRIVATE (GtkIMContextSimple)
g_io_extension_point_implement (GTK_IM_MODULE_EXTENSION_POINT_NAME,
g_define_type_id,
"gtk-im-context-simple",
10))
static void
gtk_im_context_simple_class_init (GtkIMContextSimpleClass *class)

View File

@ -31,6 +31,7 @@
#include <glib/gstdio.h>
#include <gmodule.h>
#include "gtkimmodule.h"
#include "gtkimmoduleprivate.h"
#include "gtkimcontextsimple.h"
#include "gtkmodulesprivate.h"
@ -59,594 +60,9 @@
#include <windows.h>
#endif
#undef GDK_DEPRECATED
#undef GDK_DEPRECATED_FOR
#define GDK_DEPRECATED
#define GDK_DEPRECATED_FOR(f)
/* We need to call getc() a lot in a loop. This is suboptimal,
* as getc() does thread locking on the FILE it is given.
* To optimize that, lock the file first, then call getc(),
* then unlock.
* If locking functions are not present in libc, fall back
* to the suboptimal getc().
*/
#if !defined(HAVE_FLOCKFILE) && !defined(HAVE__LOCK_FILE)
# define flockfile(f) (void)1
# define funlockfile(f) (void)1
# define getc_unlocked(f) getc(f)
#elif !defined(HAVE_FLOCKFILE) && defined(HAVE__LOCK_FILE)
# define flockfile(f) _lock_file(f)
# define funlockfile(f) _unlock_file(f)
# define getc_unlocked(f) _getc_nolock(f)
#endif
#define SIMPLE_ID "gtk-im-context-simple"
#define NONE_ID "gtk-im-context-none"
/**
* GtkIMContextInfo:
* @context_id: The unique identification string of the input method.
* @context_name: The human-readable name of the input method.
* @domain: Translation domain to be used with dgettext()
* @domain_dirname: Name of locale directory for use with bindtextdomain()
* @default_locales: A colon-separated list of locales where this input method
* should be the default. The asterisk * sets the default for all locales.
*
* Bookkeeping information about a loadable input method.
*/
typedef struct _GtkIMModule GtkIMModule;
typedef struct _GtkIMModuleClass GtkIMModuleClass;
#define GTK_TYPE_IM_MODULE (gtk_im_module_get_type ())
#define GTK_IM_MODULE(im_module) (G_TYPE_CHECK_INSTANCE_CAST ((im_module), GTK_TYPE_IM_MODULE, GtkIMModule))
#define GTK_IS_IM_MODULE(im_module) (G_TYPE_CHECK_INSTANCE_TYPE ((im_module), GTK_TYPE_IM_MODULE))
struct _GtkIMModule
{
GTypeModule parent_instance;
gboolean builtin;
GModule *library;
void (*list) (const GtkIMContextInfo ***contexts,
guint *n_contexts);
void (*init) (GTypeModule *module);
void (*exit) (void);
GtkIMContext *(*create) (const gchar *context_id);
GtkIMContextInfo **contexts;
guint n_contexts;
gchar *path;
};
struct _GtkIMModuleClass
{
GTypeModuleClass parent_class;
};
static GType gtk_im_module_get_type (void);
static gint n_loaded_contexts = 0;
static GHashTable *contexts_hash = NULL;
static GSList *modules_list = NULL;
static gboolean
gtk_im_module_load (GTypeModule *module)
{
GtkIMModule *im_module = GTK_IM_MODULE (module);
if (!im_module->builtin)
{
im_module->library = g_module_open (im_module->path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
if (!im_module->library)
{
g_warning ("%s", g_module_error());
return FALSE;
}
/* extract symbols from the lib */
if (!g_module_symbol (im_module->library, "im_module_init",
(gpointer *)&im_module->init) ||
!g_module_symbol (im_module->library, "im_module_exit",
(gpointer *)&im_module->exit) ||
!g_module_symbol (im_module->library, "im_module_list",
(gpointer *)&im_module->list) ||
!g_module_symbol (im_module->library, "im_module_create",
(gpointer *)&im_module->create))
{
g_warning ("%s", g_module_error());
g_module_close (im_module->library);
return FALSE;
}
}
/* call the module's init function to let it */
/* setup anything it needs to set up. */
im_module->init (module);
return TRUE;
}
static void
gtk_im_module_unload (GTypeModule *module)
{
GtkIMModule *im_module = GTK_IM_MODULE (module);
im_module->exit();
if (!im_module->builtin)
{
g_module_close (im_module->library);
im_module->library = NULL;
im_module->init = NULL;
im_module->exit = NULL;
im_module->list = NULL;
im_module->create = NULL;
}
}
G_DEFINE_TYPE (GtkIMModule, gtk_im_module, G_TYPE_TYPE_MODULE)
/* This only will ever be called if an error occurs during
* initialization
*/
static void
gtk_im_module_finalize (GObject *object)
{
GtkIMModule *module = GTK_IM_MODULE (object);
g_free (module->path);
G_OBJECT_CLASS (gtk_im_module_parent_class)->finalize (object);
}
static void
gtk_im_module_class_init (GtkIMModuleClass *class)
{
GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class);
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
module_class->load = gtk_im_module_load;
module_class->unload = gtk_im_module_unload;
gobject_class->finalize = gtk_im_module_finalize;
}
static void
gtk_im_module_init (GtkIMModule* object)
{
}
static void
free_info (GtkIMContextInfo *info)
{
g_free ((char *)info->context_id);
g_free ((char *)info->context_name);
g_free ((char *)info->domain);
g_free ((char *)info->domain_dirname);
g_free ((char *)info->default_locales);
g_free (info);
}
static void
add_module (GtkIMModule *module, GSList *infos)
{
GSList *tmp_list = infos;
gint i = 0;
gint n = g_slist_length (infos);
module->contexts = g_new (GtkIMContextInfo *, n);
while (tmp_list)
{
GtkIMContextInfo *info = tmp_list->data;
if (g_hash_table_lookup (contexts_hash, info->context_id))
{
free_info (info); /* Duplicate */
}
else
{
g_hash_table_insert (contexts_hash, (char *)info->context_id, module);
module->contexts[i++] = tmp_list->data;
n_loaded_contexts++;
}
tmp_list = tmp_list->next;
}
g_slist_free (infos);
module->n_contexts = i;
modules_list = g_slist_prepend (modules_list, module);
}
#ifdef G_OS_WIN32
static void
correct_libdir_prefix (gchar **path)
{
/* GTK_LIBDIR is the build-time libdir */
if (strncmp (*path, GTK_LIBDIR, strlen (GTK_LIBDIR)) == 0)
{
/* This is an entry put there by make install on the
* packager's system. On Windows a prebuilt GTK+
* package can be installed in a random
* location. The gtk.immodules file distributed in
* such a package contains paths from the package
* builder's machine. Replace the path with the real
* one on this machine.
*/
gchar *tem = *path;
*path = g_strconcat (_gtk_get_libdir (), tem + strlen (GTK_LIBDIR), NULL);
g_free (tem);
}
}
static void
correct_localedir_prefix (gchar **path)
{
/* See above */
if (strncmp (*path, GTK_LOCALEDIR, strlen (GTK_LOCALEDIR)) == 0)
{
gchar *tem = *path;
*path = g_strconcat (_gtk_get_localedir (), tem + strlen (GTK_LOCALEDIR), NULL);
g_free (tem);
}
}
#endif
G_GNUC_UNUSED static GtkIMModule *
add_builtin_module (const gchar *module_name,
const GtkIMContextInfo **contexts,
int n_contexts)
{
GtkIMModule *module = g_object_new (GTK_TYPE_IM_MODULE, NULL);
GSList *infos = NULL;
int i;
for (i = 0; i < n_contexts; i++)
{
GtkIMContextInfo *info = g_new (GtkIMContextInfo, 1);
info->context_id = g_strdup (contexts[i]->context_id);
info->context_name = g_strdup (contexts[i]->context_name);
info->domain = g_strdup (contexts[i]->domain);
info->domain_dirname = g_strdup (contexts[i]->domain_dirname);
#ifdef G_OS_WIN32
correct_localedir_prefix ((char **) &info->domain_dirname);
#endif
info->default_locales = g_strdup (contexts[i]->default_locales);
infos = g_slist_prepend (infos, info);
}
module->builtin = TRUE;
g_type_module_set_name (G_TYPE_MODULE (module), module_name);
add_module (module, infos);
return module;
}
/*
* gtk_get_im_module_path:
*
* Obtains the path in which to look for IM modules. See the documentation
* of the `GTK_PATH`
* environment variable for more details about looking up modules. This
* function is useful solely for utilities supplied with GTK+ and should
* not be used by applications under normal circumstances.
*
* Returns: (type filename): a newly-allocated string containing the
* path in which to look for IM modules.
*/
gchar *
gtk_get_im_module_path (void)
{
gchar **paths = _gtk_get_module_path ("immodules");
gchar *result = g_strjoinv (G_SEARCHPATH_SEPARATOR_S, paths);
g_strfreev (paths);
return result;
}
/*
* gtk_get_im_module_file:
*
* Obtains the path to the IM modules file. See the documentation
* of the `GTK_IM_MODULE_FILE`
* environment variable for more details.
*
* Returns: (type filename): a newly-allocated string containing the
* name of the file listing the IM modules available for loading
*/
gchar *
gtk_get_im_module_file (void)
{
const gchar *var = g_getenv ("GTK_IM_MODULE_FILE");
gchar *result = NULL;
if (var)
result = g_strdup (var);
if (!result)
{
gchar *path;
var = g_getenv ("GTK_EXE_PREFIX");
if (var)
path = g_build_filename (var, "lib", "gtk-4.0", GTK_BINARY_VERSION, "immodules.cache", NULL);
else
path = g_build_filename (_gtk_get_libdir (), "gtk-4.0", GTK_BINARY_VERSION, "immodules.cache", NULL);
return path;
}
return result;
}
static void
gtk_im_module_initialize (void)
{
GString *line_buf = g_string_new (NULL);
GString *tmp_buf = g_string_new (NULL);
gchar *filename = gtk_get_im_module_file();
FILE *file;
gboolean have_error = FALSE;
GtkIMModule *module = NULL;
GSList *infos = NULL;
contexts_hash = g_hash_table_new (g_str_hash, g_str_equal);
#define do_builtin(m) \
{ \
const GtkIMContextInfo **contexts; \
int n_contexts; \
extern void _gtk_immodule_ ## m ## _list (const GtkIMContextInfo ***contexts, \
int *n_contexts); \
extern void _gtk_immodule_ ## m ## _init (GTypeModule *module); \
extern void _gtk_immodule_ ## m ## _exit (void); \
extern GtkIMContext *_gtk_immodule_ ## m ## _create (const gchar *context_id); \
\
_gtk_immodule_ ## m ## _list (&contexts, &n_contexts); \
module = add_builtin_module (#m, contexts, n_contexts); \
module->init = _gtk_immodule_ ## m ## _init; \
module->exit = _gtk_immodule_ ## m ## _exit; \
module->create = _gtk_immodule_ ## m ## _create; \
module = NULL; \
}
#ifdef INCLUDE_IM_ime
do_builtin (ime);
#endif
#ifdef INCLUDE_IM_xim
do_builtin (xim);
#endif
#ifdef INCLUDE_IM_broadway
do_builtin (broadway);
#endif
#ifdef INCLUDE_IM_wayland
do_builtin (wayland);
#endif
#undef do_builtin
file = g_fopen (filename, "r");
if (!file)
{
/* In case someone wants only the default input method,
* we allow no file at all.
*/
g_string_free (line_buf, TRUE);
g_string_free (tmp_buf, TRUE);
g_free (filename);
return;
}
while (!have_error && gtk_read_line (file, line_buf))
{
const char *p;
p = line_buf->str;
if (!gtk_skip_space (&p))
{
/* Blank line marking the end of a module
*/
if (module && *p != '#')
{
add_module (module, infos);
module = NULL;
infos = NULL;
}
continue;
}
if (!module)
{
/* Read a module location
*/
module = g_object_new (GTK_TYPE_IM_MODULE, NULL);
if (!gtk_scan_string (&p, tmp_buf) || gtk_skip_space (&p))
{
g_warning ("Error parsing context info in '%s'\n %s", filename, line_buf->str);
have_error = TRUE;
}
module->path = g_strdup (tmp_buf->str);
#ifdef G_OS_WIN32
correct_libdir_prefix (&module->path);
#endif
g_type_module_set_name (G_TYPE_MODULE (module), module->path);
}
else
{
GtkIMContextInfo *info = g_new0 (GtkIMContextInfo, 1);
/* Read information about a context type
*/
if (!gtk_scan_string (&p, tmp_buf))
goto context_error;
info->context_id = g_strdup (tmp_buf->str);
if (!gtk_scan_string (&p, tmp_buf))
goto context_error;
info->context_name = g_strdup (tmp_buf->str);
if (!gtk_scan_string (&p, tmp_buf))
goto context_error;
info->domain = g_strdup (tmp_buf->str);
if (!gtk_scan_string (&p, tmp_buf))
goto context_error;
info->domain_dirname = g_strdup (tmp_buf->str);
#ifdef G_OS_WIN32
correct_localedir_prefix ((char **) &info->domain_dirname);
#endif
if (!gtk_scan_string (&p, tmp_buf))
goto context_error;
info->default_locales = g_strdup (tmp_buf->str);
if (gtk_skip_space (&p))
goto context_error;
infos = g_slist_prepend (infos, info);
continue;
context_error:
g_warning ("Error parsing context info in '%s'\n %s", filename, line_buf->str);
have_error = TRUE;
}
}
if (have_error)
{
g_slist_free_full (infos, (GDestroyNotify)free_info);
g_object_unref (module);
}
else if (module)
add_module (module, infos);
fclose (file);
g_string_free (line_buf, TRUE);
g_string_free (tmp_buf, TRUE);
g_free (filename);
}
static gint
compare_gtkimcontextinfo_name (const GtkIMContextInfo **a,
const GtkIMContextInfo **b)
{
return g_utf8_collate ((*a)->context_name, (*b)->context_name);
}
/**
* _gtk_im_module_list:
* @contexts: location to store an array of pointers to #GtkIMContextInfo
* this array should be freed with g_free() when you are finished.
* The structures it points are statically allocated and should
* not be modified or freed.
* @n_contexts: the length of the array stored in @contexts
*
* List all available types of input method context
*/
void
_gtk_im_module_list (const GtkIMContextInfo ***contexts,
guint *n_contexts)
{
int n = 0;
static
#ifndef G_OS_WIN32
const
#endif
GtkIMContextInfo simple_context_info = {
SIMPLE_ID,
NC_("input method menu", "Simple"),
GETTEXT_PACKAGE,
#ifdef GTK_LOCALEDIR
GTK_LOCALEDIR,
#else
"",
#endif
""
};
static
#ifndef G_OS_WIN32
const
#endif
GtkIMContextInfo none_context_info = {
NONE_ID,
NC_("input method menu", "None"),
GETTEXT_PACKAGE,
#ifdef GTK_LOCALEDIR
GTK_LOCALEDIR,
#else
"",
#endif
""
};
#ifdef G_OS_WIN32
static gboolean beenhere = FALSE;
#endif
if (!contexts_hash)
gtk_im_module_initialize ();
#ifdef G_OS_WIN32
if (!beenhere)
{
beenhere = TRUE;
/* correct_localedir_prefix() requires its parameter to be a
* malloced string
*/
simple_context_info.domain_dirname = g_strdup (simple_context_info.domain_dirname);
correct_localedir_prefix ((char **) &simple_context_info.domain_dirname);
none_context_info.domain_dirname = g_strdup (none_context_info.domain_dirname);
correct_localedir_prefix ((char **) &none_context_info.domain_dirname);
}
#endif
if (n_contexts)
*n_contexts = n_loaded_contexts + 2;
if (contexts)
{
GSList *tmp_list;
int i;
*contexts = g_new (const GtkIMContextInfo *, n_loaded_contexts + 2);
(*contexts)[n++] = &none_context_info;
(*contexts)[n++] = &simple_context_info;
tmp_list = modules_list;
while (tmp_list)
{
GtkIMModule *module = tmp_list->data;
for (i=0; i<module->n_contexts; i++)
(*contexts)[n++] = module->contexts[i];
tmp_list = tmp_list->next;
}
/* first elements (Simple and None) should always be at top */
qsort ((*contexts)+2, n-2, sizeof (GtkIMContextInfo *), (GCompareFunc)compare_gtkimcontextinfo_name);
}
}
/**
* _gtk_im_module_create:
* @context_id: the context ID for the context type to create
@ -660,85 +76,54 @@ _gtk_im_module_list (const GtkIMContextInfo ***contexts,
GtkIMContext *
_gtk_im_module_create (const gchar *context_id)
{
GtkIMModule *im_module;
GIOExtensionPoint *ep;
GIOExtension *ext;
GType type;
GtkIMContext *context = NULL;
if (strcmp (context_id, NONE_ID) == 0)
return NULL;
if (!contexts_hash)
gtk_im_module_initialize ();
if (strcmp (context_id, SIMPLE_ID) != 0)
ep = g_io_extension_point_lookup (GTK_IM_MODULE_EXTENSION_POINT_NAME);
ext = g_io_extension_point_get_extension_by_name (ep, context_id);
if (ext)
{
im_module = g_hash_table_lookup (contexts_hash, context_id);
if (!im_module)
{
g_warning ("Attempt to load unknown IM context type '%s'", context_id);
}
else
{
if (g_type_module_use (G_TYPE_MODULE (im_module)))
{
context = im_module->create (context_id);
g_type_module_unuse (G_TYPE_MODULE (im_module));
}
if (!context)
g_warning ("Loading IM context type '%s' failed", context_id);
}
type = g_io_extension_get_type (ext);
context = g_object_new (type, NULL);
}
if (!context)
return gtk_im_context_simple_new ();
else
return context;
}
/* Match @locale against @against.
*
* 'en_US' against en_US => 4
* 'en_US' against en => 3
* 'en', en_UK against en_US => 2
* all locales, against * => 1
*/
static gint
match_locale (const gchar *locale,
const gchar *against,
gint against_len)
{
if (strcmp (against, "*") == 0)
return 1;
if (g_ascii_strcasecmp (locale, against) == 0)
return 4;
if (g_ascii_strncasecmp (locale, against, 2) == 0)
return (against_len == 2) ? 3 : 2;
return 0;
return context;
}
static gboolean
match_backend (GtkIMContextInfo *context)
is_platform (const char *context_id)
{
return g_strcmp0 (context_id, "wayland") == 0 ||
g_strcmp0 (context_id, "broadway") == 0 ||
g_strcmp0 (context_id, "xim") == 0 ||
g_strcmp0 (context_id, "ime") == 0;
}
static gboolean
match_backend (const char *context_id)
{
#ifdef GDK_WINDOWING_WAYLAND
if (g_strcmp0 (context->context_id, "wayland") == 0)
if (g_strcmp0 (context_id, "wayland") == 0)
return GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ());
#endif
#ifdef GDK_WINDOWING_BROADWAY
if (g_strcmp0 (context->context_id, "broadway") == 0)
if (g_strcmp0 (context_id, "broadway") == 0)
return GDK_IS_BROADWAY_DISPLAY (gdk_display_get_default ());
#endif
#ifdef GDK_WINDOWING_X11
if (g_strcmp0 (context->context_id, "xim") == 0)
if (g_strcmp0 (context_id, "xim") == 0)
return GDK_IS_X11_DISPLAY (gdk_display_get_default ());
#endif
#ifdef GDK_WINDOWING_WIN32
if (g_strcmp0 (context->context_id, "ime") == 0)
if (g_strcmp0 (context_id, "ime") == 0)
return GDK_IS_WIN32_DISPLAY (gdk_display_get_default ());
#endif
@ -755,81 +140,21 @@ lookup_immodule (gchar **immodules_list)
else if (g_strcmp0 (*immodules_list, NONE_ID) == 0)
return NONE_ID;
else
{
gboolean found;
gchar *context_id;
found = g_hash_table_lookup_extended (contexts_hash, *immodules_list,
(gpointer *) &context_id, NULL);
if (found)
return context_id;
}
{
GIOExtensionPoint *ep;
GIOExtension *ext;
ep = g_io_extension_point_lookup (GTK_IM_MODULE_EXTENSION_POINT_NAME);
ext = g_io_extension_point_get_extension_by_name (ep, *immodules_list);
if (ext)
return g_io_extension_get_name (ext);
}
immodules_list++;
}
return NULL;
}
#ifdef G_OS_WIN32
/* max size for LOCALE_SISO639LANGNAME and LOCALE_SISO3166CTRYNAME is 9 */
#define MAX_NAME_SIZE 9
static gchar *
get_current_input_language (void)
{
LCID lcid;
LANGID langid;
HKL kblayout;
int name_size;
wchar_t name[MAX_NAME_SIZE];
gchar *language;
gchar *country;
gchar *full;
/* Current thread's keyboard layout */
kblayout = GetKeyboardLayout(0);
/* lowest word in the HKL is the LANGID */
langid = LOWORD (kblayout);
/* LCID is the LANGID without order */
lcid = langid;
/* Get Language ID */
name_size = GetLocaleInfoW (lcid, LOCALE_SISO639LANGNAME, NULL, 0);
if (name_size <= 1)
return NULL;
g_assert (name_size <= MAX_NAME_SIZE);
GetLocaleInfoW (lcid, LOCALE_SISO639LANGNAME, name, name_size);
language = g_utf16_to_utf8 (name, name_size, NULL, NULL, NULL);
if (!language)
return NULL;
if (SUBLANGID (langid) == SUBLANG_NEUTRAL)
return language;
/* Get Country ID */
name_size = GetLocaleInfoW (lcid, LOCALE_SISO3166CTRYNAME, NULL, 0);
if (name_size <= 1)
return language;
g_assert (name_size <= MAX_NAME_SIZE);
GetLocaleInfoW (lcid, LOCALE_SISO3166CTRYNAME, name, name_size);
country = g_utf16_to_utf8 (name, name_size, NULL, NULL, NULL);
if (!country)
return language;
full = g_strdup_printf ("%s_%s", language, country);
g_free (language);
g_free (country);
return full;
}
#endif
/**
* _gtk_im_module_get_default_context_id:
*
@ -841,26 +166,21 @@ get_current_input_language (void)
const gchar *
_gtk_im_module_get_default_context_id (void)
{
GSList *tmp_list;
const gchar *context_id = NULL;
gint best_goodness = 0;
gint i;
gchar *tmp_locale, *tmp, **immodules;
const gchar *envvar;
GtkSettings *settings;
if (!contexts_hash)
gtk_im_module_initialize ();
char *tmp;
envvar = g_getenv ("GTK_IM_MODULE");
if (envvar)
{
immodules = g_strsplit (envvar, ":", 0);
context_id = lookup_immodule (immodules);
g_strfreev (immodules);
char **immodules;
immodules = g_strsplit (envvar, ":", 0);
context_id = lookup_immodule (immodules);
g_strfreev (immodules);
if (context_id)
return context_id;
if (context_id)
return context_id;
}
/* Check if the certain immodule is set in XSETTINGS. */
@ -868,6 +188,8 @@ _gtk_im_module_get_default_context_id (void)
g_object_get (G_OBJECT (settings), "gtk-im-module", &tmp, NULL);
if (tmp)
{
char **immodules;
immodules = g_strsplit (tmp, ":", 0);
context_id = lookup_immodule (immodules);
g_strfreev (immodules);
@ -877,57 +199,68 @@ _gtk_im_module_get_default_context_id (void)
return context_id;
}
#ifdef G_OS_WIN32
/* Read current input locale from the current keyboard info */
tmp_locale = get_current_input_language ();
if (!tmp_locale)
/* Default to system locale when input language is unknown */
tmp_locale = _gtk_get_lc_ctype ();
#else
tmp_locale = _gtk_get_lc_ctype ();
#endif
GIOExtensionPoint *ep;
GList *list, *l;
/* Strip the locale code down to the essentials
*/
tmp = strchr (tmp_locale, '.');
if (tmp)
*tmp = '\0';
tmp = strchr (tmp_locale, '@');
if (tmp)
*tmp = '\0';
tmp_list = modules_list;
while (tmp_list)
ep = g_io_extension_point_lookup (GTK_IM_MODULE_EXTENSION_POINT_NAME);
list = g_io_extension_point_get_extensions (ep);
for (l = list; l; l = l->next)
{
GtkIMModule *module = tmp_list->data;
GIOExtension *ext = l->data;
const char *context_id;
for (i = 0; i < module->n_contexts; i++)
{
const gchar *p;
context_id = g_io_extension_get_name (ext);
if (match_backend (context_id))
return context_id;
if (!match_backend (module->contexts[i]))
continue;
p = module->contexts[i]->default_locales;
while (p)
{
const gchar *q = strchr (p, ':');
gint goodness = match_locale (tmp_locale, p, q ? q - p : strlen (p));
if (goodness > best_goodness)
{
context_id = module->contexts[i]->context_id;
best_goodness = goodness;
}
p = q ? q + 1 : NULL;
}
}
tmp_list = tmp_list->next;
// FIXME: locale matching
if (!is_platform (context_id))
return context_id;
}
g_free (tmp_locale);
return context_id ? context_id : SIMPLE_ID;
}
void
gtk_im_modules_init (void)
{
GIOExtensionPoint *ep;
GIOModuleScope *scope;
char **paths;
int i;
GTK_NOTE (MODULES,
g_print ("Registering extension point %s\n", GTK_IM_MODULE_EXTENSION_POINT_NAME));
ep = g_io_extension_point_register (GTK_IM_MODULE_EXTENSION_POINT_NAME);
g_io_extension_point_set_required_type (ep, GTK_TYPE_IM_CONTEXT);
g_type_ensure (gtk_im_context_simple_get_type ());
// other builtin im context types go here
scope = g_io_module_scope_new (G_IO_MODULE_SCOPE_BLOCK_DUPLICATES);
paths = _gtk_get_module_path ("immodules");
for (i = 0; paths[i]; i++)
{
GTK_NOTE (MODULES,
g_print ("Scanning io modules in %s\n", paths[i]));
g_io_modules_scan_all_in_directory_with_scope (paths[i], scope);
}
g_strfreev (paths);
g_io_module_scope_free (scope);
{
GList *list, *l;
list = g_io_extension_point_get_extensions (ep);
for (l = list; l; l = l->next)
{
GIOExtension *ext = l->data;
g_print ("extension: %s: type %s\n",
g_io_extension_get_name (ext),
g_type_name (g_io_extension_get_type (ext)));
}
}
}

View File

@ -20,15 +20,12 @@
#include <gtk/gtk.h>
/* The following entry points are exported by each input method module
*/
G_BEGIN_DECLS
/*
void im_module_list (const GtkIMContextInfo ***contexts,
guint *n_contexts);
void im_module_init (GtkModule *module);
void im_module_exit (void);
GtkIMContext *im_module_create (const gchar *context_id);
*/
void gtk_im_modules_init (void);
#define GTK_IM_MODULE_EXTENSION_POINT_NAME "gtk-im-module"
G_END_DECLS
#endif /* __GTK_IM_MODULE_H__ */

View File

@ -20,21 +20,12 @@
#include <gdk/gdk.h>
#include "gtkimcontext.h"
#include "gtkimcontextinfo.h"
G_BEGIN_DECLS
void _gtk_im_module_list (const GtkIMContextInfo ***contexts,
guint *n_contexts);
GtkIMContext * _gtk_im_module_create (const gchar *context_id);
const gchar * _gtk_im_module_get_default_context_id (void);
/* Needs to be exported API for gtk-queryimmodules */
GDK_AVAILABLE_IN_ALL
gchar * gtk_get_im_module_path (void);
GDK_AVAILABLE_IN_ALL
gchar * gtk_get_im_module_file (void);
G_END_DECLS
#endif /* __GTK_IM_MODULE_PRIVATE_H__ */

View File

@ -130,6 +130,7 @@
#include "gtkwindowprivate.h"
#include "gtkwindowgroup.h"
#include "gtkprintbackend.h"
#include "gtkimmodule.h"
#include "a11y/gtkaccessibility.h"
@ -628,6 +629,8 @@ gettext_initialization (void)
static void
default_display_notify_cb (GdkDisplayManager *dm)
{
gtk_print_backends_init ();
gtk_im_modules_init ();
_gtk_accessibility_init ();
debug_flags[0].display = gdk_display_get_default ();
}
@ -656,8 +659,6 @@ do_post_parse_initialization (void)
_gtk_accel_map_init ();
gtk_print_backends_init ();
gtk_initialized = TRUE;
display_manager = gdk_display_manager_get ();

View File

@ -464,7 +464,6 @@ gtk_public_headers = files([
'gtkiconview.h',
'gtkimage.h',
'gtkimcontext.h',
'gtkimcontextinfo.h',
'gtkimcontextsimple.h',
'gtkimmodule.h',
'gtkimmulticontext.h',
@ -893,7 +892,7 @@ foreach m: dyn_im_method_defs # populated in modules/input/meson.build
im_args = m[2]
im_libs = m[3]
shared_module('im-@0@'.format(im_name), im_srcs, gen_headers,
shared_module('libim-@0@'.format(im_name), im_srcs, gen_headers,
c_args: im_args,
include_directories: [confinc, gdkinc, gtkinc],
dependencies: gtk_deps + im_libs,
@ -1045,7 +1044,6 @@ gtk_tools = [
['gtk4-builder-tool', ['gtk-builder-tool.c']],
['gtk4-update-icon-cache', ['updateiconcache.c', 'gtkiconcachevalidator.c']],
['gtk4-encode-symbolic-svg', ['encodesymbolic.c', 'gdkpixbufutils.c']],
['gtk4-query-immodules', ['queryimmodules.c', 'gtkutils.c']],
]
if os_unix

View File

@ -1,247 +0,0 @@
/* GTK+
* querymodules.c:
*
* Copyright (C) 2000-2010 Red Hat Software
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <glib.h>
#include <glib/gprintf.h>
#include <errno.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef USE_LA_MODULES
#define SOEXT ".la"
#else
#define SOEXT ("." G_MODULE_SUFFIX)
#endif
#include "gtk/gtkimcontextinfo.h"
#include "gtk/gtkimmoduleprivate.h"
#include "gtk/gtkversion.h"
#include "gtk/gtkutilsprivate.h"
static void
escape_string (GString *contents, const char *str)
{
while (TRUE)
{
char c = *str++;
switch (c)
{
case '\0':
goto done;
case '\n':
g_string_append (contents, "\\n");
break;
case '\"':
g_string_append (contents, "\\\"");
break;
#ifdef G_OS_WIN32
/* Replace backslashes in path with forward slashes, so that
* it reads in without problems.
*/
case '\\':
g_string_append (contents, "/");
break;
#endif
default:
g_string_append_c (contents, c);
}
}
done:;
}
static void
print_escaped (GString *contents, const char *str)
{
g_string_append_c (contents, '"');
escape_string (contents, str);
g_string_append_c (contents, '"');
g_string_append_c (contents, ' ');
}
static gboolean
query_module (const char *dir, const char *name, GString *contents)
{
void (*list) (const GtkIMContextInfo ***contexts,
guint *n_contexts);
gpointer list_ptr;
gpointer init_ptr;
gpointer exit_ptr;
gpointer create_ptr;
GModule *module;
gchar *path;
gboolean error = FALSE;
if (g_path_is_absolute (name))
path = g_strdup (name);
else
path = g_build_filename (dir, name, NULL);
module = g_module_open (path, 0);
if (!module)
{
g_fprintf (stderr, "Cannot load module %s: %s\n", path, g_module_error());
error = TRUE;
}
if (module &&
g_module_symbol (module, "im_module_list", &list_ptr) &&
g_module_symbol (module, "im_module_init", &init_ptr) &&
g_module_symbol (module, "im_module_exit", &exit_ptr) &&
g_module_symbol (module, "im_module_create", &create_ptr))
{
const GtkIMContextInfo **contexts;
guint n_contexts;
int i;
list = list_ptr;
print_escaped (contents, path);
g_string_append_c (contents, '\n');
(*list) (&contexts, &n_contexts);
for (i = 0; i < n_contexts; i++)
{
print_escaped (contents, contexts[i]->context_id);
print_escaped (contents, contexts[i]->context_name);
print_escaped (contents, contexts[i]->domain);
print_escaped (contents, contexts[i]->domain_dirname);
print_escaped (contents, contexts[i]->default_locales);
g_string_append_c (contents, '\n');
}
g_string_append_c (contents, '\n');
}
else
{
g_fprintf (stderr, "%s does not export GTK+ IM module API: %s\n", path,
g_module_error ());
error = TRUE;
}
g_free (path);
if (module)
g_module_close (module);
return error;
}
int main (int argc, char **argv)
{
char *cwd;
int i;
char *path;
gboolean error = FALSE;
gchar *cache_file = NULL;
gint first_file = 1;
GString *contents;
if (argc > 1 && strcmp (argv[1], "--update-cache") == 0)
{
cache_file = gtk_get_im_module_file ();
first_file = 2;
}
contents = g_string_new ("");
g_string_append_printf (contents,
"# GTK+ Input Method Modules file\n"
"# Automatically generated file, do not edit\n"
"# Created by %s from gtk+-%d.%d.%d\n"
"#\n",
argv[0],
GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
if (argc == first_file) /* No file arguments given */
{
char **dirs;
GHashTable *dirs_done;
path = gtk_get_im_module_path ();
g_string_append_printf (contents, "# ModulesPath = %s\n#\n", path);
dirs = gtk_split_file_list (path);
dirs_done = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
for (i = 0; dirs[i]; i++)
if (!g_hash_table_lookup (dirs_done, dirs[i]))
{
GDir *dir = g_dir_open (dirs[i], 0, NULL);
if (dir)
{
const char *dent;
GList *list = NULL, *iterator = NULL;
while ((dent = g_dir_read_name (dir)))
list = g_list_prepend (list, g_strdup (dent));
list = g_list_sort (list, (GCompareFunc) strcmp);
for (iterator = list; iterator; iterator = iterator->next)
{
if (g_str_has_suffix (iterator->data, SOEXT))
error |= query_module (dirs[i], iterator->data, contents);
}
g_list_free_full (list, g_free);
g_dir_close (dir);
}
g_hash_table_insert (dirs_done, dirs[i], GUINT_TO_POINTER (TRUE));
}
g_hash_table_destroy (dirs_done);
}
else
{
cwd = g_get_current_dir ();
for (i = first_file; i < argc; i++)
error |= query_module (cwd, argv[i], contents);
g_free (cwd);
}
if (!error)
{
if (cache_file)
{
GError *err;
err = NULL;
if (!g_file_set_contents (cache_file, contents->str, -1, &err))
{
g_fprintf (stderr, "%s\n", err->message);
error = 1;
}
}
else
g_print ("%s\n", contents->str);
}
return error ? 1 : 0;
}

View File

@ -125,29 +125,38 @@ static void cb_client_widget_hierarchy_changed (GtkWidget *widget,
GtkWidget *widget2,
GtkIMContextIME *context_ime);
GType gtk_type_im_context_ime = 0;
static GObjectClass *parent_class;
#define GTK_TYPE_IM_CONTEXT_IME (gtk_im_context_ime_get_type ())
#define GTK_IM_CONTEXT_IME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_IM_CONTEXT_IME, GtkIMContextIME))
G_DEFINE_DYNAMIC_TYPE (GtkIMContextIME, gtk_im_context_ime, GTK_TYPE_IM_CONTEXT)
void
gtk_im_context_ime_register_type (GTypeModule *type_module)
g_io_module_load (GIOModule *module)
{
const GTypeInfo im_context_ime_info = {
sizeof (GtkIMContextIMEClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) gtk_im_context_ime_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GtkIMContextIME),
0,
(GInstanceInitFunc) gtk_im_context_ime_init,
g_type_module_use (G_TYPE_MODULE (module));
gtk_im_context_ime_register_type (G_TYPE_MODULE (module));
g_io_extension_point_implement (GTK_IM_MODULE_EXTENSION_POINT_NAME,
GTK_TYPE_IM_CONTEXT_IME,
"ime",
10);
}
void
g_io_module_unload (GIOModule *module)
{
}
char **
g_io_module_query (void)
{
char *eps[] = {
GTK_IM_MODULE_EXTENSION_POINT_NAME,
NULL
};
gtk_type_im_context_ime =
g_type_module_register_type (type_module,
GTK_TYPE_IM_CONTEXT,
"GtkIMContextIME", &im_context_ime_info, 0);
return g_strdupv (eps);
}
static void
@ -156,8 +165,6 @@ gtk_im_context_ime_class_init (GtkIMContextIMEClass *class)
GtkIMContextClass *im_context_class = GTK_IM_CONTEXT_CLASS (class);
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
parent_class = g_type_class_peek_parent (class);
gobject_class->finalize = gtk_im_context_ime_finalize;
gobject_class->dispose = gtk_im_context_ime_dispose;
gobject_class->set_property = gtk_im_context_ime_set_property;
@ -173,6 +180,10 @@ gtk_im_context_ime_class_init (GtkIMContextIMEClass *class)
im_context_class->set_use_preedit = gtk_im_context_ime_set_use_preedit;
}
static void
gtk_im_context_ime_class_finalize (GtkIMContextIMEClass *class)
{
}
static void
gtk_im_context_ime_init (GtkIMContextIME *context_ime)

View File

@ -21,8 +21,6 @@
#include <gtk/gtk.h>
extern GType gtk_type_im_context_ime;
#define GTK_TYPE_IM_CONTEXT_IME gtk_type_im_context_ime
#define GTK_IM_CONTEXT_IME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_IM_CONTEXT_IME, GtkIMContextIME))
#define GTK_IM_CONTEXT_IME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_IM_CONTEXT_IME, GtkIMContextIMEClass))

View File

@ -20,6 +20,7 @@
#include <string.h>
#include <stdlib.h>
#include "gtkimmodule.h"
#include "gtkimcontextxim.h"
#include "gtk/gtkintl.h"
@ -145,38 +146,43 @@ static void xim_info_display_closed (GdkDisplay *display,
gboolean is_error,
GtkXIMInfo *info);
static GObjectClass *parent_class;
G_DEFINE_DYNAMIC_TYPE (GtkIMContextXIM, gtk_im_context_xim, GTK_TYPE_IM_CONTEXT)
GType gtk_type_im_context_xim = 0;
void
g_io_module_load (GIOModule *module)
{
g_type_module_use (G_TYPE_MODULE (module));
g_print ("load io module for x11\n");
gtk_im_context_xim_register_type (G_TYPE_MODULE (module));
g_io_extension_point_implement (GTK_IM_MODULE_EXTENSION_POINT_NAME,
GTK_TYPE_IM_CONTEXT_XIM,
"xim",
10);
}
void
g_io_module_unload (GIOModule *module)
{
}
char **
g_io_module_query (void)
{
char *eps[] = {
GTK_IM_MODULE_EXTENSION_POINT_NAME,
NULL
};
return g_strdupv (eps);
}
static GSList *open_ims = NULL;
/* List of status windows for different toplevels */
static GSList *status_windows = NULL;
void
gtk_im_context_xim_register_type (GTypeModule *type_module)
{
const GTypeInfo im_context_xim_info =
{
sizeof (GtkIMContextXIMClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) gtk_im_context_xim_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GtkIMContextXIM),
0,
(GInstanceInitFunc) gtk_im_context_xim_init,
};
gtk_type_im_context_xim =
g_type_module_register_type (type_module,
GTK_TYPE_IM_CONTEXT,
"GtkIMContextXIM",
&im_context_xim_info, 0);
}
#define PREEDIT_MASK (XIMPreeditCallbacks | XIMPreeditPosition | \
XIMPreeditArea | XIMPreeditNothing | XIMPreeditNone)
#define STATUS_MASK (XIMStatusCallbacks | XIMStatusArea | \
@ -475,8 +481,6 @@ gtk_im_context_xim_class_init (GtkIMContextXIMClass *class)
GtkIMContextClass *im_context_class = GTK_IM_CONTEXT_CLASS (class);
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
parent_class = g_type_class_peek_parent (class);
im_context_class->set_client_widget = gtk_im_context_xim_set_client_widget;
im_context_class->filter_keypress = gtk_im_context_xim_filter_keypress;
im_context_class->reset = gtk_im_context_xim_reset;
@ -488,6 +492,11 @@ gtk_im_context_xim_class_init (GtkIMContextXIMClass *class)
gobject_class->finalize = gtk_im_context_xim_finalize;
}
static void
gtk_im_context_xim_class_finalize (GtkIMContextXIMClass *class)
{
}
static void
gtk_im_context_xim_init (GtkIMContextXIM *im_context_xim)
{
@ -534,7 +543,7 @@ gtk_im_context_xim_finalize (GObject *obj)
g_free (context_xim->locale);
g_free (context_xim->mb_charset);
G_OBJECT_CLASS (parent_class)->finalize (obj);
G_OBJECT_CLASS (gtk_im_context_xim_parent_class)->finalize (obj);
}
static void

View File

@ -23,9 +23,7 @@
G_BEGIN_DECLS
extern GType gtk_type_im_context_xim;
#define GTK_TYPE_IM_CONTEXT_XIM (gtk_type_im_context_xim)
#define GTK_TYPE_IM_CONTEXT_XIM (gtk_im_context_xim_get_type ())
#define GTK_IM_CONTEXT_XIM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_IM_CONTEXT_XIM, GtkIMContextXIM))
#define GTK_IM_CONTEXT_XIM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_IM_CONTEXT_XIM, GtkIMContextXIMClass))
#define GTK_IS_IM_CONTEXT_XIM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_IM_CONTEXT_XIM))
@ -41,7 +39,6 @@ struct _GtkIMContextXIMClass
GtkIMContextClass parent_class;
};
void gtk_im_context_xim_register_type (GTypeModule *type_module);
GtkIMContext *gtk_im_context_xim_new (void);
void gtk_im_context_xim_shutdown (void);

View File

@ -27,9 +27,9 @@
#include "gdk/broadway/gdkbroadway.h"
#define GTK_IM_CONTEXT_TYPE_BROADWAY (type_broadway)
#define GTK_IM_CONTEXT_BROADWAY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_IM_CONTEXT_TYPE_BROADWAY, GtkIMContextBroadway))
#define GTK_IM_CONTEXT_BROADWAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_IM_CONTEXT_TYPE_BROADWAY, GtkIMContextBroadwayClass))
#define GTK_TYPE_IM_CONTEXT_BROADWAY (gtk_im_context_broadway_get_type ())
#define GTK_IM_CONTEXT_BROADWAY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_IM_CONTEXT_BROADWAY, GtkIMContextBroadway))
#define GTK_IM_CONTEXT_BROADWAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_IM_CONTEXT_BROADWAY, GtkIMContextBroadwayClass))
typedef struct _GtkIMContextBroadway
{
@ -42,28 +42,38 @@ typedef struct _GtkIMContextBroadwayClass
GtkIMContextSimpleClass parent_class;
} GtkIMContextBroadwayClass;
GType type_broadway = 0;
static GObjectClass *parent_class;
G_DEFINE_DYNAMIC_TYPE (GtkIMContextBroadway, gtk_im_context_broadway, GTK_TYPE_IM_CONTEXT_SIMPLE)
static const GtkIMContextInfo imbroadway_info =
void
g_io_module_load (GIOModule *module)
{
"broadway", /* ID */
NC_("input method menu", "Broadway"), /* Human readable name */
GETTEXT_PACKAGE, /* Translation domain */
GTK_LOCALEDIR, /* Dir for bindtextdomain (not strictly needed for "gtk+") */
"", /* Languages for which this module is the default */
};
g_type_module_use (G_TYPE_MODULE (module));
static const GtkIMContextInfo *info_list[] =
g_print ("load io module for broadway\n");
gtk_im_context_broadway_register_type (G_TYPE_MODULE (module));
g_io_extension_point_implement (GTK_IM_MODULE_EXTENSION_POINT_NAME,
GTK_TYPE_IM_CONTEXT_BROADWAY,
"broadway",
10);
}
void
g_io_module_unload (GIOModule *module)
{
&imbroadway_info,
};
}
char **
g_io_module_query (void)
{
char *eps[] = {
GTK_IM_MODULE_EXTENSION_POINT_NAME,
NULL
};
return g_strdupv (eps);
}
#ifndef INCLUDE_IM_broadway
#define MODULE_ENTRY(type,function) G_MODULE_EXPORT type im_module_ ## function
#else
#define MODULE_ENTRY(type, function) type _gtk_immodule_broadway_ ## function
#endif
static void
broadway_set_client_widget (GtkIMContext *context, GtkWidget *widget)
@ -100,9 +110,9 @@ broadway_focus_out (GtkIMContext *context)
}
static void
gtk_im_context_broadway_class_init (GtkIMContextClass *klass)
gtk_im_context_broadway_class_init (GtkIMContextBroadwayClass *class)
{
parent_class = g_type_class_peek_parent (klass);
GtkIMContextClass *klass = GTK_IM_CONTEXT_CLASS (class);
klass->focus_in = broadway_focus_in;
klass->focus_out = broadway_focus_out;
@ -110,52 +120,11 @@ gtk_im_context_broadway_class_init (GtkIMContextClass *klass)
}
static void
gtk_im_context_broadway_init (GtkIMContext *im_context)
gtk_im_context_broadway_class_finalize (GtkIMContextBroadwayClass *class)
{
}
static void
gtk_im_context_broadway_register_type (GTypeModule *module)
{
const GTypeInfo object_info =
{
sizeof (GtkIMContextBroadwayClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) gtk_im_context_broadway_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GtkIMContextBroadway),
0,
(GInstanceInitFunc) gtk_im_context_broadway_init,
};
type_broadway =
g_type_module_register_type (module,
GTK_TYPE_IM_CONTEXT_SIMPLE,
"GtkIMContextBroadway",
&object_info, 0);
}
MODULE_ENTRY (void, init) (GTypeModule * module)
{
gtk_im_context_broadway_register_type (module);
}
MODULE_ENTRY (void, exit) (void)
gtk_im_context_broadway_init (GtkIMContextBroadway *im_context)
{
}
MODULE_ENTRY (void, list) (const GtkIMContextInfo *** contexts, int *n_contexts)
{
*contexts = info_list;
*n_contexts = G_N_ELEMENTS (info_list);
}
MODULE_ENTRY (GtkIMContext *, create) (const gchar * context_id)
{
if (!strcmp (context_id, "broadway"))
return g_object_new (type_broadway, NULL);
else
return NULL;
}

View File

@ -1,69 +0,0 @@
/*
* gtkimmoduleime
* Copyright (C) 2003 Takuro Ashie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* $Id$
*/
#include "config.h"
#include <string.h>
#include "gtk/gtkintl.h"
#include "gtk/gtkimmodule.h"
#include "gtkimcontextime.h"
static const GtkIMContextInfo ime_info = {
"ime",
NC_("input method menu", "Windows IME"),
GETTEXT_PACKAGE,
"",
"ja:ko:zh",
};
static const GtkIMContextInfo *info_list[] = {
&ime_info,
};
#ifndef INCLUDE_IM_ime
#define MODULE_ENTRY(type,function) G_MODULE_EXPORT type im_module_ ## function
#else
#define MODULE_ENTRY(type, function) type _gtk_immodule_ime_ ## function
#endif
MODULE_ENTRY (void, init) (GTypeModule * module)
{
gtk_im_context_ime_register_type (module);
}
MODULE_ENTRY (void, exit) (void)
{
}
MODULE_ENTRY (void, list) (const GtkIMContextInfo *** contexts, int *n_contexts)
{
*contexts = info_list;
*n_contexts = G_N_ELEMENTS (info_list);
}
MODULE_ENTRY (GtkIMContext *, create) (const gchar * context_id)
{
g_return_val_if_fail (context_id, NULL);
if (!strcmp (context_id, "ime"))
return g_object_new (GTK_TYPE_IM_CONTEXT_IME, NULL);
else
return NULL;
}

View File

@ -32,6 +32,7 @@
#define GTK_IM_CONTEXT_QUARTZ(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_IM_CONTEXT_TYPE_QUARTZ, GtkIMContextQuartz))
#define GTK_IM_CONTEXT_QUARTZ_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_IM_CONTEXT_TYPE_QUARTZ, GtkIMContextQuartzClass))
typedef struct _GtkIMContextQuartz
{
GtkIMContext parent;
@ -49,28 +50,41 @@ typedef struct _GtkIMContextQuartzClass
GtkIMContextClass parent_class;
} GtkIMContextQuartzClass;
GType type_quartz = 0;
static GObjectClass *parent_class;
G_DEFINE_DYNAMIC_TYPE (GtkIMContextQuartz, gtk_im_context_quartz, GTK_TYPE_IM_CONTEXT)
static const GtkIMContextInfo imquartz_info =
void
g_io_module_load (GIOModule *module)
{
"quartz",
NC_("input method menu", "Mac OS X Quartz"),
GETTEXT_PACKAGE,
GTK_LOCALEDIR,
"ja:ko:zh:*",
};
g_type_module_use (G_TYPE_MODULE (module));
static const GtkIMContextInfo *info_list[] =
g_print ("load io module for quartz\n");
gtk_im_context_quartz_register_type (G_TYPE_MODULE (module));
g_io_extension_point_implement (GTK_IM_MODULE_EXTENSION_POINT_NAME,
GTK_TYPE_IM_CONTEXT_BROADWAY,
"quartz",
10);
}
void
g_io_module_unload (GIOModule *module)
{
&imquartz_info,
};
}
char **
g_io_module_query (void)
{
char *eps[] = {
GTK_IM_MODULE_EXTENSION_POINT_NAME,
NULL
};
return g_strdupv (eps);
}
#ifndef INCLUDE_IM_quartz
#define MODULE_ENTRY(type,function) G_MODULE_EXPORT type im_module_ ## function
#else
#define MODULE_ENTRY(type, function) type _gtk_immodule_quartz_ ## function
#endif
static void
quartz_get_preedit_string (GtkIMContext *context,
@ -359,16 +373,16 @@ imquartz_finalize (GObject *obj)
g_signal_handlers_disconnect_by_func (qc->slave, (gpointer)commit_cb, qc);
g_object_unref (qc->slave);
parent_class->finalize (obj);
gtk_im_context_quartz_parent_class->finalize (obj);
}
static void
gtk_im_context_quartz_class_init (GtkIMContextClass *klass)
gtk_im_context_quartz_class_init (GtkIMContextQuartzClass *class)
{
GTK_NOTE (MISC, g_print ("gtk_im_context_quartz_class_init\n"));
GObjectClass *object_class = G_OBJECT_CLASS (klass);
parent_class = g_type_class_peek_parent (klass);
GtkIMContextClass *klass = GTK_IM_CONTEXT_CLASS (class);
GObjectClass *object_class = G_OBJECT_CLASS (class);
klass->get_preedit_string = quartz_get_preedit_string;
klass->filter_keypress = quartz_filter_keypress;
@ -383,11 +397,15 @@ gtk_im_context_quartz_class_init (GtkIMContextClass *klass)
}
static void
gtk_im_context_quartz_init (GtkIMContext *im_context)
gtk_im_context_quartz_class_finalize (GtkIMContextQuartzClass *class)
{
}
static void
gtk_im_context_quartz_init (GtkIMContextQuartz *qc)
{
GTK_NOTE (MISC, g_print ("gtk_im_context_quartz_init\n"));
GtkIMContextQuartz *qc = GTK_IM_CONTEXT_QUARTZ (im_context);
qc->preedit_str = g_strdup ("");
qc->cursor_index = 0;
qc->selected_len = 0;
@ -397,54 +415,3 @@ gtk_im_context_quartz_init (GtkIMContext *im_context)
qc->slave = g_object_new (GTK_TYPE_IM_CONTEXT_SIMPLE, NULL);
g_signal_connect (G_OBJECT (qc->slave), "commit", G_CALLBACK (commit_cb), qc);
}
static void
gtk_im_context_quartz_register_type (GTypeModule *module)
{
const GTypeInfo object_info =
{
sizeof (GtkIMContextQuartzClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) gtk_im_context_quartz_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GtkIMContextQuartz),
0,
(GInstanceInitFunc) gtk_im_context_quartz_init,
};
type_quartz =
g_type_module_register_type (module,
GTK_TYPE_IM_CONTEXT,
"GtkIMContextQuartz",
&object_info, 0);
}
MODULE_ENTRY (void, init) (GTypeModule * module)
{
gtk_im_context_quartz_register_type (module);
}
MODULE_ENTRY (void, exit) (void)
{
}
MODULE_ENTRY (void, list) (const GtkIMContextInfo *** contexts, int *n_contexts)
{
*contexts = info_list;
*n_contexts = G_N_ELEMENTS (info_list);
}
MODULE_ENTRY (GtkIMContext *, create) (const gchar * context_id)
{
g_return_val_if_fail (context_id, NULL);
if (!strcmp (context_id, "quartz"))
{
GTK_NOTE (MISC, g_print ("immodule_quartz create\n"));
return g_object_new (type_quartz, NULL);
}
else
return NULL;
}

View File

@ -70,31 +70,47 @@ struct _GtkIMContextWayland
guint use_preedit : 1;
};
GType type_wayland = 0;
static GObjectClass *parent_class;
static GtkIMContextWaylandGlobal *global = NULL;
static const GtkIMContextInfo imwayland_info =
static void gtk_im_context_wayland_global_init (GdkDisplay *display);
#define GTK_TYPE_IM_CONTEXT_WAYLAND (gtk_im_context_wayland_get_type ())
#define GTK_IM_CONTEXT_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_IM_CONTEXT_WAYLAND, GtkIMContextWayland))
G_DEFINE_DYNAMIC_TYPE (GtkIMContextWayland, gtk_im_context_wayland, GTK_TYPE_IM_CONTEXT_SIMPLE)
void
g_io_module_load (GIOModule *module)
{
"wayland", /* ID */
NC_("input method menu", "Wayland"), /* Human readable name */
GETTEXT_PACKAGE, /* Translation domain */
GTK_LOCALEDIR, /* Dir for bindtextdomain (not strictly needed for "gtk+") */
"", /* Languages for which this module is the default */
};
g_type_module_use (G_TYPE_MODULE (module));
static const GtkIMContextInfo *info_list[] =
g_print ("load io module for wayland\n");
gtk_im_context_wayland_register_type (G_TYPE_MODULE (module));
gtk_im_context_wayland_global_init (gdk_display_get_default ());
g_io_extension_point_implement (GTK_IM_MODULE_EXTENSION_POINT_NAME,
GTK_TYPE_IM_CONTEXT_WAYLAND,
"wayland",
10);
}
void
g_io_module_unload (GIOModule *module)
{
&imwayland_info,
};
}
char **
g_io_module_query (void)
{
char *eps[] = {
GTK_IM_MODULE_EXTENSION_POINT_NAME,
NULL
};
return g_strdupv (eps);
}
#define GTK_IM_CONTEXT_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), type_wayland, GtkIMContextWayland))
#ifndef INCLUDE_IM_wayland
#define MODULE_ENTRY(type,function) G_MODULE_EXPORT type im_module_ ## function
#else
#define MODULE_ENTRY(type, function) type _gtk_immodule_wayland_ ## function
#endif
static void
reset_preedit (GtkIMContextWayland *context)
@ -237,7 +253,8 @@ static const struct wl_registry_listener registry_listener = {
static void
gtk_im_context_wayland_global_init (GdkDisplay *display)
{
g_return_if_fail (global == NULL);
if (global)
return;
global = g_new0 (GtkIMContextWaylandGlobal, 1);
global->display = gdk_wayland_display_get_wl_display (display);
@ -395,7 +412,7 @@ gtk_im_context_wayland_finalize (GObject *object)
g_clear_object (&context->widget);
g_clear_object (&context->gesture);
G_OBJECT_CLASS (parent_class)->finalize (object);
G_OBJECT_CLASS (gtk_im_context_wayland_parent_class)->finalize (object);
}
static void
@ -472,7 +489,7 @@ gtk_im_context_wayland_get_preedit_string (GtkIMContext *context,
GtkIMContextWayland *context_wayland = GTK_IM_CONTEXT_WAYLAND (context);
gchar *preedit_str;
GTK_IM_CONTEXT_CLASS (parent_class)->get_preedit_string (context, str, attrs, cursor_pos);
GTK_IM_CONTEXT_CLASS (gtk_im_context_wayland_parent_class)->get_preedit_string (context, str, attrs, cursor_pos);
/* If the parent implementation returns a len>0 string, go with it */
if (str && *str && **str)
@ -499,7 +516,7 @@ gtk_im_context_wayland_filter_keypress (GtkIMContext *context,
GdkEventKey *key)
{
/* This is done by the compositor */
return GTK_IM_CONTEXT_CLASS (parent_class)->filter_keypress (context, key);
return GTK_IM_CONTEXT_CLASS (gtk_im_context_wayland_parent_class)->filter_keypress (context, key);
}
static void
@ -535,7 +552,7 @@ gtk_im_context_wayland_reset (GtkIMContext *context)
{
reset_preedit (GTK_IM_CONTEXT_WAYLAND (context));
GTK_IM_CONTEXT_CLASS (parent_class)->reset (context);
GTK_IM_CONTEXT_CLASS (gtk_im_context_wayland_parent_class)->reset (context);
}
static void
@ -613,8 +630,11 @@ gtk_im_context_wayland_class_init (GtkIMContextWaylandClass *klass)
im_context_class->set_use_preedit = gtk_im_context_wayland_set_use_preedit;
im_context_class->set_surrounding = gtk_im_context_wayland_set_surrounding;
im_context_class->get_surrounding = gtk_im_context_wayland_get_surrounding;
}
parent_class = g_type_class_peek_parent (klass);
static void
gtk_im_context_wayland_class_finalize (GtkIMContextWaylandClass *class)
{
}
static void
@ -633,46 +653,3 @@ gtk_im_context_wayland_init (GtkIMContextWayland *context)
g_signal_connect_swapped (context, "notify::input-hints",
G_CALLBACK (on_content_type_changed), context);
}
static void
gtk_im_context_wayland_register_type (GTypeModule *module)
{
const GTypeInfo object_info = {
sizeof (GtkIMContextWaylandClass),
NULL, NULL,
(GClassInitFunc) gtk_im_context_wayland_class_init,
NULL, NULL,
sizeof (GtkIMContextWayland),
0,
(GInstanceInitFunc) gtk_im_context_wayland_init,
};
type_wayland = g_type_module_register_type (module,
GTK_TYPE_IM_CONTEXT_SIMPLE,
"GtkIMContextWayland",
&object_info, 0);
}
MODULE_ENTRY (void, init) (GTypeModule * module)
{
gtk_im_context_wayland_register_type (module);
gtk_im_context_wayland_global_init (gdk_display_get_default ());
}
MODULE_ENTRY (void, exit) (void)
{
}
MODULE_ENTRY (void, list) (const GtkIMContextInfo *** contexts, int *n_contexts)
{
*contexts = info_list;
*n_contexts = G_N_ELEMENTS (info_list);
}
MODULE_ENTRY (GtkIMContext *, create) (const gchar * context_id)
{
if (strcmp (context_id, "wayland") == 0)
return g_object_new (type_wayland, NULL);
else
return NULL;
}

View File

@ -1,65 +0,0 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2000 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gtk/gtkintl.h"
#include "gtk/gtkimmodule.h"
#include "gtkimcontextxim.h"
#include <string.h>
static const GtkIMContextInfo xim_ja_info = {
"xim", /* ID */
NC_("input method menu", "X Input Method"), /* Human readable name */
GETTEXT_PACKAGE, /* Translation domain */
GTK_LOCALEDIR, /* Dir for bindtextdomain (not strictly needed for "gtk+") */
"ko:ja:th:zh" /* Languages for which this module is the default */
};
static const GtkIMContextInfo *info_list[] = {
&xim_ja_info
};
#ifndef INCLUDE_IM_xim
#define MODULE_ENTRY(type, function) G_MODULE_EXPORT type im_module_ ## function
#else
#define MODULE_ENTRY(type, function) type _gtk_immodule_xim_ ## function
#endif
MODULE_ENTRY (void, init) (GTypeModule *type_module)
{
gtk_im_context_xim_register_type (type_module);
}
MODULE_ENTRY (void, exit) (void)
{
gtk_im_context_xim_shutdown ();
}
MODULE_ENTRY (void, list) (const GtkIMContextInfo ***contexts,
int *n_contexts)
{
*contexts = info_list;
*n_contexts = G_N_ELEMENTS (info_list);
}
MODULE_ENTRY (GtkIMContext *, create) (const gchar *context_id)
{
if (strcmp (context_id, "xim") == 0)
return gtk_im_context_xim_new ();
else
return NULL;
}

View File

@ -87,8 +87,8 @@ endforeach
method_defs = [
['broadway', files('imbroadway.c')],
['quartz', ('imquartz.c'), [], ('-xobjective-c')],
['xim', files('gtkimcontextxim.c', 'imxim.c')],
['ime', files('gtkimcontextime.c', 'imime.c'), ['imm32']],
['xim', files('gtkimcontextxim.c')],
['ime', files('gtkimcontextime.c'), ['imm32']],
['wayland', im_wayland_sources],
]