1/* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.Free
16 */
17
18/*
19 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
20 * file for a list of people on the GTK+ Team. See the ChangeLog
21 * files for a list of changes. These files are distributed with
22 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
23 */
24
25#include "config.h"
26
27#include <errno.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31
32#include <glib/gstdio.h>
33#include <gmodule.h>
34#include "gtkimmodule.h"
35#include "gtkimmoduleprivate.h"
36#include "gtkimcontextsimple.h"
37#include "gtkmodulesprivate.h"
38#include "gtksettings.h"
39#include "gtkprivate.h"
40#include "gtkintl.h"
41
42#ifdef GDK_WINDOWING_X11
43#include "x11/gdkx.h"
44#endif
45
46#ifdef GDK_WINDOWING_WAYLAND
47#include "wayland/gdkwayland.h"
48#include "gtkimcontextwayland.h"
49#endif
50
51#ifdef GDK_WINDOWING_BROADWAY
52#include "broadway/gdkbroadway.h"
53#include "gtkimcontextbroadway.h"
54#endif
55
56#ifdef GDK_WINDOWING_WIN32
57#include "win32/gdkwin32.h"
58#include "gtkimcontextime.h"
59#endif
60
61#ifdef GDK_WINDOWING_MACOS
62#include "macos/gdkmacos.h"
63#include "gtkimcontextquartz.h"
64#endif
65
66#ifdef G_OS_WIN32
67#include <windows.h>
68#endif
69
70#define SIMPLE_ID "gtk-im-context-simple"
71#define NONE_ID "gtk-im-context-none"
72
73/**
74 * _gtk_im_module_create:
75 * @context_id: the context ID for the context type to create
76 *
77 * Create an IM context of a type specified by the string
78 * ID @context_id.
79 *
80 * Returns: a newly created input context of or @context_id, or
81 * if that could not be created, a newly created `GtkIMContextSimple`
82 */
83GtkIMContext *
84_gtk_im_module_create (const char *context_id)
85{
86 GIOExtensionPoint *ep;
87 GIOExtension *ext;
88 GType type;
89 GtkIMContext *context = NULL;
90
91 if (strcmp (s1: context_id, NONE_ID) == 0)
92 return NULL;
93
94 ep = g_io_extension_point_lookup (GTK_IM_MODULE_EXTENSION_POINT_NAME);
95 ext = g_io_extension_point_get_extension_by_name (extension_point: ep, name: context_id);
96 if (ext)
97 {
98 type = g_io_extension_get_type (extension: ext);
99 context = g_object_new (object_type: type, NULL);
100 }
101
102 return context;
103}
104
105static gboolean
106match_backend (GdkDisplay *display,
107 const char *context_id)
108{
109 if (g_strcmp0 (str1: context_id, str2: "wayland") == 0)
110 {
111#ifdef GDK_WINDOWING_WAYLAND
112 return GDK_IS_WAYLAND_DISPLAY (display) &&
113 gdk_wayland_display_query_registry (display,
114 global: "zwp_text_input_manager_v3");
115#else
116 return FALSE;
117#endif
118 }
119
120 if (g_strcmp0 (str1: context_id, str2: "broadway") == 0)
121#ifdef GDK_WINDOWING_BROADWAY
122 return GDK_IS_BROADWAY_DISPLAY (display);
123#else
124 return FALSE;
125#endif
126
127 if (g_strcmp0 (str1: context_id, str2: "ime") == 0)
128#ifdef GDK_WINDOWING_WIN32
129 return GDK_IS_WIN32_DISPLAY (display);
130#else
131 return FALSE;
132#endif
133
134 if (g_strcmp0 (str1: context_id, str2: "quartz") == 0)
135#ifdef GDK_WINDOWING_MACOS
136 return GDK_IS_MACOS_DISPLAY (display);
137#else
138 return FALSE;
139#endif
140
141 return TRUE;
142}
143
144static const char *
145lookup_immodule (GdkDisplay *display,
146 char **immodules_list)
147{
148 guint i;
149
150 for (i = 0; immodules_list[i]; i++)
151 {
152 if (!match_backend (display, context_id: immodules_list[i]))
153 continue;
154
155 if (g_strcmp0 (str1: immodules_list[i], SIMPLE_ID) == 0)
156 return SIMPLE_ID;
157 else if (g_strcmp0 (str1: immodules_list[i], NONE_ID) == 0)
158 return NONE_ID;
159 else
160 {
161 GIOExtensionPoint *ep;
162 GIOExtension *ext;
163
164 ep = g_io_extension_point_lookup (GTK_IM_MODULE_EXTENSION_POINT_NAME);
165 ext = g_io_extension_point_get_extension_by_name (extension_point: ep, name: immodules_list[i]);
166 if (ext)
167 return g_io_extension_get_name (extension: ext);
168 }
169 }
170
171 return NULL;
172}
173
174/**
175 * _gtk_im_module_get_default_context_id:
176 * @display: The display to look up the module for
177 *
178 * Return the context_id of the best IM context type
179 * for the given window.
180 *
181 * Returns: the context ID (will never be %NULL)
182 */
183const char *
184_gtk_im_module_get_default_context_id (GdkDisplay *display)
185{
186 const char *context_id = NULL;
187 const char *envvar;
188 GtkSettings *settings;
189 GIOExtensionPoint *ep;
190 GList *l;
191 char *tmp;
192
193 envvar = g_getenv (variable: "GTK_IM_MODULE");
194 if (envvar)
195 {
196 char **immodules;
197 immodules = g_strsplit (string: envvar, delimiter: ":", max_tokens: 0);
198 context_id = lookup_immodule (display, immodules_list: immodules);
199 g_strfreev (str_array: immodules);
200
201 if (context_id)
202 return context_id;
203 }
204
205 /* Check if the certain immodule is set in XSETTINGS. */
206 settings = gtk_settings_get_for_display (display);
207 g_object_get (G_OBJECT (settings), first_property_name: "gtk-im-module", &tmp, NULL);
208 if (tmp)
209 {
210 char **immodules;
211
212 immodules = g_strsplit (string: tmp, delimiter: ":", max_tokens: 0);
213 context_id = lookup_immodule (display, immodules_list: immodules);
214 g_strfreev (str_array: immodules);
215 g_free (mem: tmp);
216
217 if (context_id)
218 return context_id;
219 }
220
221 ep = g_io_extension_point_lookup (GTK_IM_MODULE_EXTENSION_POINT_NAME);
222 for (l = g_io_extension_point_get_extensions (extension_point: ep); l; l = l->next)
223 {
224 GIOExtension *ext = l->data;
225
226 context_id = g_io_extension_get_name (extension: ext);
227 if (match_backend (display, context_id))
228 return context_id;
229 }
230
231 g_error ("GTK was run without any IM module being present. This must not happen.");
232
233 return SIMPLE_ID;
234}
235
236void
237gtk_im_module_ensure_extension_point (void)
238{
239 GIOExtensionPoint *ep;
240 static gboolean registered = FALSE;
241
242 if (registered)
243 return;
244
245 GTK_NOTE (MODULES,
246 g_print ("Registering extension point %s\n", GTK_IM_MODULE_EXTENSION_POINT_NAME));
247
248 ep = g_io_extension_point_register (GTK_IM_MODULE_EXTENSION_POINT_NAME);
249 g_io_extension_point_set_required_type (extension_point: ep, GTK_TYPE_IM_CONTEXT);
250
251 registered = TRUE;
252}
253
254void
255gtk_im_modules_init (void)
256{
257 GIOModuleScope *scope;
258 char **paths;
259 int i;
260
261 gtk_im_module_ensure_extension_point ();
262
263 g_type_ensure (type: gtk_im_context_simple_get_type ());
264#ifdef GDK_WINDOWING_WAYLAND
265 g_type_ensure (type: gtk_im_context_wayland_get_type ());
266#endif
267#ifdef GDK_WINDOWING_BROADWAY
268 g_type_ensure (gtk_im_context_broadway_get_type ());
269#endif
270#ifdef GDK_WINDOWING_WIN32
271 g_type_ensure (gtk_im_context_ime_get_type ());
272#endif
273#ifdef GDK_WINDOWING_MACOS
274 g_type_ensure (gtk_im_context_quartz_get_type ());
275#endif
276
277 scope = g_io_module_scope_new (flags: G_IO_MODULE_SCOPE_BLOCK_DUPLICATES);
278
279 paths = _gtk_get_module_path (type: "immodules");
280 for (i = 0; paths[i]; i++)
281 {
282 GTK_NOTE (MODULES,
283 g_print ("Scanning io modules in %s\n", paths[i]));
284 g_io_modules_scan_all_in_directory_with_scope (dirname: paths[i], scope);
285 }
286 g_strfreev (str_array: paths);
287
288 g_io_module_scope_free (scope);
289
290 if (GTK_DEBUG_CHECK (MODULES))
291 {
292 GIOExtensionPoint *ep;
293 GList *list, *l;
294
295 ep = g_io_extension_point_lookup (GTK_IM_MODULE_EXTENSION_POINT_NAME);
296 list = g_io_extension_point_get_extensions (extension_point: ep);
297 for (l = list; l; l = l->next)
298 {
299 GIOExtension *ext = l->data;
300 g_print (format: "extension: %s: type %s\n",
301 g_io_extension_get_name (extension: ext),
302 g_type_name (type: g_io_extension_get_type (extension: ext)));
303 }
304 }
305}
306

source code of gtk/gtk/gtkimmodule.c