diff options
author | Matthias Clasen <mclasen@redhat.com> | 2018-02-23 14:59:49 -0500 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2018-02-24 21:34:40 -0500 |
commit | 15cc20e7b5d46656b83a39f086650555e369aa1b (patch) | |
tree | cf7a33557fcd456d606439fe1aa5e9efd729d591 /modules | |
parent | 29bcc38ae62e73b76f0f663e2ecc5e85bfe4ca46 (diff) | |
download | gtk+-15cc20e7b5d46656b83a39f086650555e369aa1b.tar.gz |
Always include platform immodules
No need to load these as gio modules, we just include
them in libgtk.
Diffstat (limited to 'modules')
-rw-r--r-- | modules/input/gtk-text-input.xml | 302 | ||||
-rw-r--r-- | modules/input/gtkimcontextime.c | 1221 | ||||
-rw-r--r-- | modules/input/gtkimcontextime.h | 58 | ||||
-rw-r--r-- | modules/input/gtkimcontextxim.c | 1804 | ||||
-rw-r--r-- | modules/input/gtkimcontextxim.h | 48 | ||||
-rw-r--r-- | modules/input/imbroadway.c | 130 | ||||
-rw-r--r-- | modules/input/imm-extra.h | 63 | ||||
-rw-r--r-- | modules/input/imquartz.c | 417 | ||||
-rw-r--r-- | modules/input/imwayland.c | 655 | ||||
-rw-r--r-- | modules/input/meson.build | 118 | ||||
-rw-r--r-- | modules/meson.build | 2 |
11 files changed, 0 insertions, 4818 deletions
diff --git a/modules/input/gtk-text-input.xml b/modules/input/gtk-text-input.xml deleted file mode 100644 index a134a19f61..0000000000 --- a/modules/input/gtk-text-input.xml +++ /dev/null @@ -1,302 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<protocol name="gtk_text_input"> - <copyright> - Copyright © 2012, 2013 Intel Corporation - Copyright © 2015, 2016 Jan Arne Petersen - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that copyright notice and this permission - notice appear in supporting documentation, and that the name of - the copyright holders not be used in advertising or publicity - pertaining to distribution of the software without specific, - written prior permission. The copyright holders make no - representations about the suitability of this software for any - purpose. It is provided "as is" without express or implied - warranty. - - THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF - THIS SOFTWARE. - </copyright> - - <interface name="gtk_text_input" version="1"> - <description summary="text input"> - The gtk_text_input interface represents text input and input methods - associated with a seat. It provides enter/leave events to follow the - text input focus for a seat. - - Requests are used to enable/disable the text-input object and set - state information like surrounding and selected text or the content type. - The information about the entered text is sent to the text-input object - via the pre-edit and commit_string events. Using this interface removes - the need for applications to directly process hardware key events and - compose text out of them. - - Text is valid UTF-8 encoded, indices and lengths are in bytes. Indices - have to always point to the first byte of an UTF-8 encoded code point. - Lengths are not allowed to contain just a part of an UTF-8 encoded code - point. - - Focus moving throughout surfaces will result in the emission of - gtk_text_input.enter and gtk_text_input.leave events. The focused - surface must perform gtk_text_input.enable and - gtk_text_input.disable requests as the keyboard focus moves across - editable and non-editable elements of the UI. Those two requests are not - expected to be paired with each other, the compositor must be able to - handle consecutive series of the same request. - - State is sent by the state requests (set_surrounding_text, - set_content_type and set_cursor_rectangle) and a commit request. - After an enter event or disable request all state information is - invalidated and needs to be resent by the client. - - This protocol defines requests and events necessary for regular clients - to communicate with an input method. The gtk_input_method protocol - defines the interfaces necessary to implement standalone input methods. - If a compositor implements both interfaces, it will be the arbiter of the - communication between both. - - Warning! The protocol described in this file is experimental and - backward incompatible changes may be made. Backward compatible changes - may be added together with the corresponding interface version bump. - Backward incompatible changes are done by bumping the version number in - the protocol and interface names and resetting the interface version. - Once the protocol is to be declared stable, the 'z' prefix and the - version number in the protocol and interface names are removed and the - interface version number is reset. - </description> - - <request name="destroy" type="destructor"> - <description summary="Destroy the wp_text_input"> - Destroy the wp_text_input object. Also disables all surfaces enabled - through this wp_text_input object - </description> - </request> - - <enum name="enable_flags" bitfield="true"> - <description summary="enable flags"> - Content hint is a bitmask to allow to modify the behavior of the text - input. - </description> - <entry name="none" value="0x0" summary="no special behaviour"/> - <entry name="can_show_preedit" value="0x1" summary="hints that the UI is capable of showing pre-edit text"/> - <entry name="toggle_input_panel" value="0x2" summary="requests toggling input panel (eg. on-screen keyboard)"/> - </enum> - - <request name="enable"> - <description summary="Request text input to be enabled"> - Requests text input on a surface. The serial provided must be the one - received on gtk_text_input.enter. - </description> - <arg name="serial" type="uint" summary="serial of enter event"/> - <arg name="show_input_panel" type="uint" summary="details of the enable request"/> - </request> - - <request name="disable"> - <description summary="Disable text input on a surface"> - Explicitly disable text input in a surface (typically when there is no - focus on any text entry inside the surface). - </description> - </request> - - <request name="set_surrounding_text"> - <description summary="sets the surrounding text"> - Sets the plain surrounding text around the input position. Text is - UTF-8 encoded. Cursor is the byte offset within the surrounding text. - Anchor is the byte offset of the selection anchor within the - surrounding text. If there is no selected text, anchor is the same as - cursor. - - Make sure to always send some text before and after the cursor - except when the cursor is at the beginning or end of text. - - When there was a configure_surrounding_text event take the - before_cursor and after_cursor arguments into account for picking how - much surrounding text to send. - - There is a maximum length of wayland messages so text can not be - longer than 4000 bytes. - </description> - <arg name="text" type="string"/> - <arg name="cursor" type="int"/> - <arg name="anchor" type="int"/> - </request> - - <enum name="content_hint" bitfield="true"> - <description summary="content hint"> - Content hint is a bitmask to allow to modify the behavior of the text - input. - </description> - <entry name="none" value="0x0" summary="no special behaviour"/> - <entry name="completion" value="0x1" summary="suggest word completions"/> - <entry name="spellcheck" value="0x2" summary="suggest word corrections"/> - <entry name="auto_capitalization" value="0x4" summary="switch to uppercase letters at the start of a sentence"/> - <entry name="lowercase" value="0x8" summary="prefer lowercase letters"/> - <entry name="uppercase" value="0x10" summary="prefer uppercase letters"/> - <entry name="titlecase" value="0x20" summary="prefer casing for titles and headings (can be language dependent)"/> - <entry name="hidden_text" value="0x40" summary="characters should be hidden"/> - <entry name="sensitive_data" value="0x80" summary="typed text should not be stored"/> - <entry name="latin" value="0x100" summary="just latin characters should be entered"/> - <entry name="multiline" value="0x200" summary="the text input is multiline"/> - </enum> - - <enum name="content_purpose"> - <description summary="content purpose"> - The content purpose allows to specify the primary purpose of a text - input. - - This allows an input method to show special purpose input panels with - extra characters or to disallow some characters. - </description> - <entry name="normal" value="0" summary="default input, allowing all characters"/> - <entry name="alpha" value="1" summary="allow only alphabetic characters"/> - <entry name="digits" value="2" summary="allow only digits"/> - <entry name="number" value="3" summary="input a number (including decimal separator and sign)"/> - <entry name="phone" value="4" summary="input a phone number"/> - <entry name="url" value="5" summary="input an URL"/> - <entry name="email" value="6" summary="input an email address"/> - <entry name="name" value="7" summary="input a name of a person"/> - <entry name="password" value="8" summary="input a password (combine with password or sensitive_data hint)"/> - <entry name="pin" value="9" summary="input is a numeric password (combine with password or sensitive_data hint)"/> - <entry name="date" value="10" summary="input a date"/> - <entry name="time" value="11" summary="input a time"/> - <entry name="datetime" value="12" summary="input a date and time"/> - <entry name="terminal" value="13" summary="input for a terminal"/> - </enum> - - <request name="set_content_type"> - <description summary="set content purpose and hint"> - Sets the content purpose and content hint. While the purpose is the - basic purpose of an input field, the hint flags allow to modify some - of the behavior. - - When no content type is explicitly set, a normal content purpose with - none hint should be assumed. - </description> - <arg name="hint" type="uint" enum="content_hint"/> - <arg name="purpose" type="uint" enum="content_purpose"/> - </request> - - <request name="set_cursor_rectangle"> - <description summary="set cursor position"> - Sets the cursor outline as a x, y, width, height rectangle in surface - local coordinates. - - Allows the compositor to put a window with word suggestions near the - cursor. - </description> - <arg name="x" type="int"/> - <arg name="y" type="int"/> - <arg name="width" type="int"/> - <arg name="height" type="int"/> - </request> - - <request name="commit"> - <description summary="commit state"> - Allows to atomically send state updates from client. The previous - set_surrounding_text, set_content_type and set_cursor_rectangle - become effective after this call. - - Serial should be set to the serial from the last wp_text_input.enter - event. - - To make sure to not receive outdated input method events after a - state update, wl_display_sync() should be called after making this - request. - </description> - </request> - - <event name="enter"> - <description summary="enter event"> - Notification that this seat's text-input focus is on a certain surface. - - When the seat has the keyboard capability the text-input focus follows - the keyboard focus. - </description> - <arg name="serial" type="uint" summary="serial"/> - <arg name="surface" type="object" interface="wl_surface"/> - </event> - - <event name="leave"> - <description summary="leave event"> - Notification that this seat's text-input focus is no longer on - a certain surface. The client should reset any preedit string previously - set. - - The leave notification is sent before the enter notification - for the new focus. - - When the seat has the keyboard capability the text-input focus follows - the keyboard focus. - </description> - <arg name="serial" type="uint"/> - <arg name="surface" type="object" interface="wl_surface"/> - </event> - - <event name="preedit_string"> - <description summary="pre-edit"> - Notify when a new composing text (pre-edit) should be set around the - current cursor position. Any previously set composing text should - be removed. - </description> - <arg name="text" type="string" allow-null="true"/> - <arg name="cursor" type="uint"/> - </event> - - <event name="commit_string"> - <description summary="text commit"> - Notify when text should be inserted into the editor widget. The text to - commit could be either just a single character after a key press or the - result of some composing (pre-edit). - - The text argument could be also null if some text is removed (see - gtk_text_input.delete_surrounding_text). - - Any previously set composing text should be removed. - </description> - <arg name="text" type="string" allow-null="true"/> - </event> - - <event name="delete_surrounding_text"> - <description summary="delete surrounding text"> - Notify when the text around the current cursor position should be - deleted. Before_length and after_length is the length (in bytes) of text - before and after the current cursor position (excluding the selection) - to delete. - - This event should be handled as part of a following commit_string or - preedit_string event. - </description> - <arg name="before_length" type="uint" summary="length of text before current cursor position"/> - <arg name="after_length" type="uint" summary="length of text after current cursor position"/> - </event> - </interface> - - <interface name="gtk_text_input_manager" version="1"> - <description summary="text input manager"> - A factory for text-input objects. This object is a global singleton. - </description> - - <request name="destroy" type="destructor"> - <description summary="Destroy the wp_text_input_manager"> - Destroy the wp_text_input_manager object. - </description> - </request> - - <request name="get_text_input"> - <description summary="create a new text input object"> - Creates a new text-input object for a given seat. - </description> - <arg name="id" type="new_id" interface="gtk_text_input"/> - <arg name="seat" type="object" interface="wl_seat"/> - </request> - </interface> -</protocol> diff --git a/modules/input/gtkimcontextime.c b/modules/input/gtkimcontextime.c deleted file mode 100644 index 212a17b669..0000000000 --- a/modules/input/gtkimcontextime.c +++ /dev/null @@ -1,1221 +0,0 @@ -/* - * gtkimcontextime.c - * Copyright (C) 2003 Takuro Ashie - * Copyright (C) 2003-2004 Kazuki IWAMOTO - * - * 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/>. - * - */ - -/* - * Please see the following site for the detail of Windows IME API. - * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/appendix/hh/appendix/imeimes2_35ph.asp - */ - -#ifdef GTK_DISABLE_DEPRECATED -#undef GTK_DISABLE_DEPRECATED -#endif - -#include "gtkimcontextime.h" - -#include "imm-extra.h" - -#include "gdk/gdkkeysyms.h" -#include "gdk/win32/gdkwin32.h" -#include "gdk/gdkkeysyms.h" - -#include <pango/pango.h> - -/* avoid warning */ -#ifdef STRICT -# undef STRICT -# include <pango/pangowin32.h> -# ifndef STRICT -# define STRICT 1 -# endif -#else /* STRICT */ -# include <pango/pangowin32.h> -#endif /* STRICT */ - -/* #define BUFSIZE 4096 */ - -#define IS_DEAD_KEY(k) \ - ((k) >= GDK_KEY_dead_grave && (k) <= (GDK_KEY_dead_dasia+1)) - -#define FREE_PREEDIT_BUFFER(ctx) \ -{ \ - g_free((ctx)->priv->comp_str); \ - g_free((ctx)->priv->read_str); \ - (ctx)->priv->comp_str = NULL; \ - (ctx)->priv->read_str = NULL; \ - (ctx)->priv->comp_str_len = 0; \ - (ctx)->priv->read_str_len = 0; \ -} - - -struct _GtkIMContextIMEPrivate -{ - /* save IME context when the client window is focused out */ - DWORD conversion_mode; - DWORD sentence_mode; - - LPVOID comp_str; - DWORD comp_str_len; - LPVOID read_str; - DWORD read_str_len; - - guint32 dead_key_keyval; -}; - - -/* GObject class methods */ -static void gtk_im_context_ime_class_init (GtkIMContextIMEClass *class); -static void gtk_im_context_ime_init (GtkIMContextIME *context_ime); -static void gtk_im_context_ime_dispose (GObject *obj); -static void gtk_im_context_ime_finalize (GObject *obj); - -static void gtk_im_context_ime_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static void gtk_im_context_ime_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); - -/* GtkIMContext's virtual functions */ -static void gtk_im_context_ime_set_client_widget (GtkIMContext *context, - GtkWidget *widget); -static gboolean gtk_im_context_ime_filter_keypress (GtkIMContext *context, - GdkEventKey *event); -static void gtk_im_context_ime_reset (GtkIMContext *context); -static void gtk_im_context_ime_get_preedit_string (GtkIMContext *context, - gchar **str, - PangoAttrList **attrs, - gint *cursor_pos); -static void gtk_im_context_ime_focus_in (GtkIMContext *context); -static void gtk_im_context_ime_focus_out (GtkIMContext *context); -static void gtk_im_context_ime_set_cursor_location (GtkIMContext *context, - GdkRectangle *area); -static void gtk_im_context_ime_set_use_preedit (GtkIMContext *context, - gboolean use_preedit); - -/* GtkIMContextIME's private functions */ -static void gtk_im_context_ime_set_preedit_font (GtkIMContext *context); - -static GdkFilterReturn -gtk_im_context_ime_message_filter (GdkXEvent *xevent, - GdkEvent *event, - gpointer data); -static void get_window_position (GdkWindow *win, - gint *x, - gint *y); -static void cb_client_widget_hierarchy_changed (GtkWidget *widget, - GtkWidget *widget2, - GtkIMContextIME *context_ime); - -#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 -g_io_module_load (GIOModule *module) -{ - 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 - }; - - return g_strdupv (eps); -} - -static void -gtk_im_context_ime_class_init (GtkIMContextIMEClass *class) -{ - GtkIMContextClass *im_context_class = GTK_IM_CONTEXT_CLASS (class); - GObjectClass *gobject_class = G_OBJECT_CLASS (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; - gobject_class->get_property = gtk_im_context_ime_get_property; - - im_context_class->set_client_widget = gtk_im_context_ime_set_client_widget; - im_context_class->filter_keypress = gtk_im_context_ime_filter_keypress; - im_context_class->reset = gtk_im_context_ime_reset; - im_context_class->get_preedit_string = gtk_im_context_ime_get_preedit_string; - im_context_class->focus_in = gtk_im_context_ime_focus_in; - im_context_class->focus_out = gtk_im_context_ime_focus_out; - im_context_class->set_cursor_location = gtk_im_context_ime_set_cursor_location; - 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) -{ - context_ime->client_window = NULL; - context_ime->toplevel = NULL; - context_ime->use_preedit = TRUE; - context_ime->preediting = FALSE; - context_ime->opened = FALSE; - context_ime->focus = FALSE; - context_ime->cursor_location.x = 0; - context_ime->cursor_location.y = 0; - context_ime->cursor_location.width = 0; - context_ime->cursor_location.height = 0; - context_ime->commit_string = NULL; - - context_ime->priv = g_malloc0 (sizeof (GtkIMContextIMEPrivate)); - context_ime->priv->conversion_mode = 0; - context_ime->priv->sentence_mode = 0; - context_ime->priv->comp_str = NULL; - context_ime->priv->comp_str_len = 0; - context_ime->priv->read_str = NULL; - context_ime->priv->read_str_len = 0; -} - - -static void -gtk_im_context_ime_dispose (GObject *obj) -{ - GtkIMContext *context = GTK_IM_CONTEXT (obj); - GtkIMContextIME *context_ime = GTK_IM_CONTEXT_IME (obj); - - if (context_ime->client_window) - gtk_im_context_ime_set_client_widget (context, NULL); - - FREE_PREEDIT_BUFFER (context_ime); - - if (G_OBJECT_CLASS (parent_class)->dispose) - G_OBJECT_CLASS (parent_class)->dispose (obj); -} - - -static void -gtk_im_context_ime_finalize (GObject *obj) -{ - /* GtkIMContext *context = GTK_IM_CONTEXT (obj); */ - GtkIMContextIME *context_ime = GTK_IM_CONTEXT_IME (obj); - - g_free (context_ime->priv); - context_ime->priv = NULL; - - if (G_OBJECT_CLASS (parent_class)->finalize) - G_OBJECT_CLASS (parent_class)->finalize (obj); -} - - -static void -gtk_im_context_ime_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GtkIMContextIME *context_ime = GTK_IM_CONTEXT_IME (object); - - g_return_if_fail (GTK_IS_IM_CONTEXT_IME (context_ime)); - - switch (prop_id) - { - default: - break; - } -} - - -static void -gtk_im_context_ime_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GtkIMContextIME *context_ime = GTK_IM_CONTEXT_IME (object); - - g_return_if_fail (GTK_IS_IM_CONTEXT_IME (context_ime)); - - switch (prop_id) - { - default: - break; - } -} - - -GtkIMContext * -gtk_im_context_ime_new (void) -{ - return g_object_new (GTK_TYPE_IM_CONTEXT_IME, NULL); -} - - -static void -gtk_im_context_ime_set_client_widget (GtkIMContext *context, - GtkWidget *widget) -{ - GtkIMContextIME *context_ime; - GtkWidget *toplevel; - GdkWindow *client_window; - - g_return_if_fail (GTK_IS_IM_CONTEXT_IME (context)); - context_ime = GTK_IM_CONTEXT_IME (context); - toplevel = gtk_widget_get_toplevel (widget); - client_window = gtk_widget_get_window (toplevel); - - if (client_window) - { - HIMC himc; - HWND hwnd; - - hwnd = gdk_win32_window_get_impl_hwnd (client_window); - himc = ImmGetContext (hwnd); - if (himc) - { - context_ime->opened = ImmGetOpenStatus (himc); - ImmGetConversionStatus (himc, - &context_ime->priv->conversion_mode, - &context_ime->priv->sentence_mode); - ImmReleaseContext (hwnd, himc); - } - } - else if (context_ime->focus) - { - gtk_im_context_ime_focus_out (context); - } - - context_ime->client_window = client_window; -} - -static gunichar -_gtk_im_context_ime_dead_key_unichar (guint keyval, - gboolean spacing) -{ - switch (keyval) - { -#define CASE(keysym, unicode, spacing_unicode) \ - case GDK_KEY_dead_##keysym: return (spacing) ? spacing_unicode : unicode; - - CASE (grave, 0x0300, 0x0060); - CASE (acute, 0x0301, 0x00b4); - CASE (circumflex, 0x0302, 0x005e); - CASE (tilde, 0x0303, 0x007e); /* Also used with perispomeni, 0x342. */ - CASE (macron, 0x0304, 0x00af); - CASE (breve, 0x0306, 0x02d8); - CASE (abovedot, 0x0307, 0x02d9); - CASE (diaeresis, 0x0308, 0x00a8); - CASE (hook, 0x0309, 0); - CASE (abovering, 0x030A, 0x02da); - CASE (doubleacute, 0x030B, 0x2dd); - CASE (caron, 0x030C, 0x02c7); - CASE (abovecomma, 0x0313, 0); /* Equivalent to psili */ - CASE (abovereversedcomma, 0x0314, 0); /* Equivalent to dasia */ - CASE (horn, 0x031B, 0); /* Legacy use for psili, 0x313 (or 0x343). */ - CASE (belowdot, 0x0323, 0); - CASE (cedilla, 0x0327, 0x00b8); - CASE (ogonek, 0x0328, 0); /* Legacy use for dasia, 0x314.*/ - CASE (iota, 0x0345, 0); - -#undef CASE - default: - return 0; - } -} - -static void -_gtk_im_context_ime_commit_unichar (GtkIMContextIME *context_ime, - gunichar c) -{ - gchar utf8[10]; - int len; - - if (context_ime->priv->dead_key_keyval != 0) - { - gunichar combining; - - combining = - _gtk_im_context_ime_dead_key_unichar (context_ime->priv->dead_key_keyval, - FALSE); - g_unichar_compose (c, combining, &c); - } - - len = g_unichar_to_utf8 (c, utf8); - utf8[len] = 0; - - g_signal_emit_by_name (context_ime, "commit", utf8); - context_ime->priv->dead_key_keyval = 0; -} - -static gboolean -gtk_im_context_ime_filter_keypress (GtkIMContext *context, - GdkEventKey *event) -{ - GtkIMContextIME *context_ime; - gboolean retval = FALSE; - guint32 c; - GdkModifierType state; - guint keyval; - - g_return_val_if_fail (GTK_IS_IM_CONTEXT_IME (context), FALSE); - g_return_val_if_fail (event, FALSE); - - if (gdk_event_get_event_type ((GdkEvent *) event) == GDK_KEY_RELEASE) - return FALSE; - - gdk_event_get_state ((GdkEvent *) event, &state); - - if (state & GDK_CONTROL_MASK) - return FALSE; - - context_ime = GTK_IM_CONTEXT_IME (context); - - if (!context_ime->focus) - return FALSE; - - if (!GDK_IS_WINDOW (context_ime->client_window)) - return FALSE; - - gdk_event_get_keyval ((GdkEvent *) event, &keyval); - - if (keyval == GDK_KEY_space && - context_ime->priv->dead_key_keyval != 0) - { - c = _gtk_im_context_ime_dead_key_unichar (context_ime->priv->dead_key_keyval, TRUE); - context_ime->priv->dead_key_keyval = 0; - _gtk_im_context_ime_commit_unichar (context_ime, c); - return TRUE; - } - - c = gdk_keyval_to_unicode (keyval); - - if (c) - { - _gtk_im_context_ime_commit_unichar (context_ime, c); - retval = TRUE; - } - else if (IS_DEAD_KEY (keyval)) - { - gunichar dead_key; - - dead_key = _gtk_im_context_ime_dead_key_unichar (keyval, FALSE); - - /* Emulate double input of dead keys */ - if (dead_key && keyval == context_ime->priv->dead_key_keyval) - { - c = _gtk_im_context_ime_dead_key_unichar (context_ime->priv->dead_key_keyval, TRUE); - context_ime->priv->dead_key_keyval = 0; - _gtk_im_context_ime_commit_unichar (context_ime, c); - _gtk_im_context_ime_commit_unichar (context_ime, c); - } - else - context_ime->priv->dead_key_keyval = keyval; - } - - return retval; -} - - -static void -gtk_im_context_ime_reset (GtkIMContext *context) -{ - GtkIMContextIME *context_ime = GTK_IM_CONTEXT_IME (context); - HWND hwnd; - HIMC himc; - - if (!context_ime->client_window) - return; - - hwnd = gdk_win32_window_get_impl_hwnd (context_ime->client_window); - himc = ImmGetContext (hwnd); - if (!himc) - return; - - if (context_ime->preediting) - { - if (ImmGetOpenStatus (himc)) - ImmNotifyIME (himc, NI_COMPOSITIONSTR, CPS_CANCEL, 0); - - context_ime->preediting = FALSE; - g_signal_emit_by_name (context, "preedit-changed"); - } - - ImmReleaseContext (hwnd, himc); -} - - -static gchar * -get_utf8_preedit_string (GtkIMContextIME *context_ime, gint *pos_ret) -{ - gchar *utf8str = NULL; - HWND hwnd; - HIMC himc; - gint pos = 0; - - if (pos_ret) - *pos_ret = 0; - - if (!context_ime->client_window) - return g_strdup (""); - hwnd = gdk_win32_window_get_impl_hwnd (context_ime->client_window); - himc = ImmGetContext (hwnd); - if (!himc) - return g_strdup (""); - - if (context_ime->preediting) - { - glong len; - - len = ImmGetCompositionStringW (himc, GCS_COMPSTR, NULL, 0); - if (len > 0) - { - GError *error = NULL; - gpointer buf = g_alloca (len); - - ImmGetCompositionStringW (himc, GCS_COMPSTR, buf, len); - len /= 2; - utf8str = g_utf16_to_utf8 (buf, len, NULL, NULL, &error); - if (error) - { - g_warning ("%s", error->message); - g_error_free (error); - } - - if (pos_ret) - { - pos = ImmGetCompositionStringW (himc, GCS_CURSORPOS, NULL, 0); - if (pos < 0 || len < pos) - { - g_warning ("ImmGetCompositionString: " - "Invalid cursor position!"); - pos = 0; - } - } - } - } - - if (!utf8str) - { - utf8str = g_strdup (""); - pos = 0; - } - - if (pos_ret) - *pos_ret = pos; - - ImmReleaseContext (hwnd, himc); - - return utf8str; -} - - -static PangoAttrList * -get_pango_attr_list (GtkIMContextIME *context_ime, const gchar *utf8str) -{ - PangoAttrList *attrs = pango_attr_list_new (); - HWND hwnd; - HIMC himc; - - if (!context_ime->client_window) - return attrs; - hwnd = gdk_win32_window_get_impl_hwnd (context_ime->client_window); - himc = ImmGetContext (hwnd); - if (!himc) - return attrs; - - if (context_ime->preediting) - { - const gchar *schr = utf8str, *echr; - guint8 *buf; - guint16 f_red, f_green, f_blue, b_red, b_green, b_blue; - glong len, spos = 0, epos, sidx = 0, eidx; - PangoAttribute *attr; - - /* - * get attributes list of IME. - */ - len = ImmGetCompositionStringW (himc, GCS_COMPATTR, NULL, 0); - buf = g_alloca (len); - ImmGetCompositionStringW (himc, GCS_COMPATTR, buf, len); - - /* - * schr and echr are pointer in utf8str. - */ - for (echr = g_utf8_next_char (utf8str); *schr != '\0'; - echr = g_utf8_next_char (echr)) - { - /* - * spos and epos are buf(attributes list of IME) position by - * bytes. - * Using the wide-char API, this value is same with UTF-8 offset. - */ - epos = g_utf8_pointer_to_offset (utf8str, echr); - - /* - * sidx and eidx are positions in utf8str by bytes. - */ - eidx = echr - utf8str; - - /* - * convert attributes list to PangoAttriute. - */ - if (*echr == '\0' || buf[spos] != buf[epos]) - { - switch (buf[spos]) - { - case ATTR_TARGET_CONVERTED: - attr = pango_attr_underline_new (PANGO_UNDERLINE_DOUBLE); - attr->start_index = sidx; - attr->end_index = eidx; - pango_attr_list_change (attrs, attr); - f_red = f_green = f_blue = 0; - b_red = b_green = b_blue = 0xffff; - break; - case ATTR_TARGET_NOTCONVERTED: - f_red = f_green = f_blue = 0xffff; - b_red = b_green = b_blue = 0; - break; - case ATTR_INPUT_ERROR: - f_red = f_green = f_blue = 0; - b_red = b_green = b_blue = 0x7fff; - break; - default: /* ATTR_INPUT,ATTR_CONVERTED,ATTR_FIXEDCONVERTED */ - attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); - attr->start_index = sidx; - attr->end_index = eidx; - pango_attr_list_change (attrs, attr); - f_red = f_green = f_blue = 0; - b_red = b_green = b_blue = 0xffff; - } - attr = pango_attr_foreground_new (f_red, f_green, f_blue); - attr->start_index = sidx; - attr->end_index = eidx; - pango_attr_list_change (attrs, attr); - attr = pango_attr_background_new (b_red, b_green, b_blue); - attr->start_index = sidx; - attr->end_index = eidx; - pango_attr_list_change (attrs, attr); - - schr = echr; - spos = epos; - sidx = eidx; - } - } - } - - ImmReleaseContext (hwnd, himc); - - return attrs; -} - - -static void -gtk_im_context_ime_get_preedit_string (GtkIMContext *context, - gchar **str, - PangoAttrList **attrs, - gint *cursor_pos) -{ - gchar *utf8str = NULL; - gint pos = 0; - GtkIMContextIME *context_ime; - - context_ime = GTK_IM_CONTEXT_IME (context); - - utf8str = get_utf8_preedit_string (context_ime, &pos); - - if (attrs) - *attrs = get_pango_attr_list (context_ime, utf8str); - - if (str) - { - *str = utf8str; - } - else - { - g_free (utf8str); - utf8str = NULL; - } - - if (cursor_pos) - *cursor_pos = pos; -} - - -static void -gtk_im_context_ime_focus_in (GtkIMContext *context) -{ - GtkIMContextIME *context_ime = GTK_IM_CONTEXT_IME (context); - GdkWindow *toplevel; - GtkWidget *widget = NULL; - HWND hwnd; - HIMC himc; - - if (!GDK_IS_WINDOW (context_ime->client_window)) - return; - - /* swtich current context */ - context_ime->focus = TRUE; - - hwnd = gdk_win32_window_get_impl_hwnd (context_ime->client_window); - himc = ImmGetContext (hwnd); - if (!himc) - return; - - toplevel = gdk_window_get_toplevel (context_ime->client_window); - if (GDK_IS_WINDOW (toplevel)) - { - gdk_window_add_filter (toplevel, - gtk_im_context_ime_message_filter, context_ime); - context_ime->toplevel = toplevel; - } - else - { - g_warning ("gtk_im_context_ime_focus_in(): " - "cannot find toplevel window."); - return; - } - - /* trace reparenting (probably no need) */ - gdk_window_get_user_data (context_ime->client_window, (gpointer) & widget); - if (GTK_IS_WIDGET (widget)) - { - g_signal_connect (widget, "hierarchy-changed", - G_CALLBACK (cb_client_widget_hierarchy_changed), - context_ime); - } - else - { - /* warning? */ - } - - /* restore preedit context */ - ImmSetConversionStatus (himc, - context_ime->priv->conversion_mode, - context_ime->priv->sentence_mode); - - if (context_ime->opened) - { - if (!ImmGetOpenStatus (himc)) - ImmSetOpenStatus (himc, TRUE); - if (context_ime->preediting) - { - ImmSetCompositionStringW (himc, - SCS_SETSTR, - context_ime->priv->comp_str, - context_ime->priv->comp_str_len, NULL, 0); - FREE_PREEDIT_BUFFER (context_ime); - } - } - - /* clean */ - ImmReleaseContext (hwnd, himc); -} - - -static void -gtk_im_context_ime_focus_out (GtkIMContext *context) -{ - GtkIMContextIME *context_ime = GTK_IM_CONTEXT_IME (context); - GdkWindow *toplevel; - GtkWidget *widget = NULL; - HWND hwnd; - HIMC himc; - - if (!GDK_IS_WINDOW (context_ime->client_window)) - return; - - /* swtich current context */ - context_ime->focus = FALSE; - - hwnd = gdk_win32_window_get_impl_hwnd (context_ime->client_window); - himc = ImmGetContext (hwnd); - if (!himc) - return; - - /* save preedit context */ - ImmGetConversionStatus (himc, - &context_ime->priv->conversion_mode, - &context_ime->priv->sentence_mode); - - if (ImmGetOpenStatus (himc)) - { - gboolean preediting = context_ime->preediting; - - if (preediting) - { - FREE_PREEDIT_BUFFER (context_ime); - - context_ime->priv->comp_str_len - = ImmGetCompositionStringW (himc, GCS_COMPSTR, NULL, 0); - context_ime->priv->comp_str - = g_malloc (context_ime->priv->comp_str_len); - ImmGetCompositionStringW (himc, GCS_COMPSTR, - context_ime->priv->comp_str, - context_ime->priv->comp_str_len); - - context_ime->priv->read_str_len - = ImmGetCompositionStringW (himc, GCS_COMPREADSTR, NULL, 0); - context_ime->priv->read_str - = g_malloc (context_ime->priv->read_str_len); - ImmGetCompositionStringW (himc, GCS_COMPREADSTR, - context_ime->priv->read_str, - context_ime->priv->read_str_len); - } - - ImmSetOpenStatus (himc, FALSE); - - context_ime->opened = TRUE; - context_ime->preediting = preediting; - } - else - { - context_ime->opened = FALSE; - context_ime->preediting = FALSE; - } - - /* remove signal handler */ - gdk_window_get_user_data (context_ime->client_window, (gpointer) & widget); - if (GTK_IS_WIDGET (widget)) - { - g_signal_handlers_disconnect_by_func - (G_OBJECT (widget), - G_CALLBACK (cb_client_widget_hierarchy_changed), context_ime); - } - - /* remove event fileter */ - toplevel = gdk_window_get_toplevel (context_ime->client_window); - if (GDK_IS_WINDOW (toplevel)) - { - gdk_window_remove_filter (toplevel, - gtk_im_context_ime_message_filter, - context_ime); - context_ime->toplevel = NULL; - } - else - { - g_warning ("gtk_im_context_ime_focus_out(): " - "cannot find toplevel window."); - } - - /* clean */ - ImmReleaseContext (hwnd, himc); -} - - -static void -gtk_im_context_ime_set_cursor_location (GtkIMContext *context, - GdkRectangle *area) -{ - gint wx = 0, wy = 0; - GtkIMContextIME *context_ime; - COMPOSITIONFORM cf; - HWND hwnd; - HIMC himc; - - g_return_if_fail (GTK_IS_IM_CONTEXT_IME (context)); - - context_ime = GTK_IM_CONTEXT_IME (context); - if (area) - context_ime->cursor_location = *area; - - if (!context_ime->client_window) - return; - - hwnd = gdk_win32_window_get_impl_hwnd (context_ime->client_window); - himc = ImmGetContext (hwnd); - if (!himc) - return; - - get_window_position (context_ime->client_window, &wx, &wy); - cf.dwStyle = CFS_POINT; - cf.ptCurrentPos.x = wx + context_ime->cursor_location.x; - cf.ptCurrentPos.y = wy + context_ime->cursor_location.y; - ImmSetCompositionWindow (himc, &cf); - - ImmReleaseContext (hwnd, himc); -} - - -static void -gtk_im_context_ime_set_use_preedit (GtkIMContext *context, - gboolean use_preedit) -{ - GtkIMContextIME *context_ime; - - g_return_if_fail (GTK_IS_IM_CONTEXT_IME (context)); - context_ime = GTK_IM_CONTEXT_IME (context); - - context_ime->use_preedit = use_preedit; - if (context_ime->preediting) - { - HWND hwnd; - HIMC himc; - - hwnd = gdk_win32_window_get_impl_hwnd (context_ime->client_window); - himc = ImmGetContext (hwnd); - if (!himc) - return; - - /* FIXME: What to do? */ - - ImmReleaseContext (hwnd, himc); - } -} - - -static void -gtk_im_context_ime_set_preedit_font (GtkIMContext *context) -{ - GtkIMContextIME *context_ime; - GtkWidget *widget = NULL; - HWND hwnd; - HIMC himc; - HKL ime = GetKeyboardLayout (0); - const gchar *lang; - gunichar wc; - PangoContext *pango_context; - PangoFont *font; - LOGFONT *logfont; - GtkStyleContext *style; - PangoFontDescription *font_desc; - - g_return_if_fail (GTK_IS_IM_CONTEXT_IME (context)); - - context_ime = GTK_IM_CONTEXT_IME (context); - if (!context_ime->client_window) - return; - - gdk_window_get_user_data (context_ime->client_window, (gpointer) &widget); - if (!GTK_IS_WIDGET (widget)) - return; - - hwnd = gdk_win32_window_get_impl_hwnd (context_ime->client_window); - himc = ImmGetContext (hwnd); - if (!himc) - return; - - /* set font */ - pango_context = gtk_widget_get_pango_context (widget); - if (!pango_context) - goto ERROR_OUT; - - /* Try to make sure we use a font that actually can show the - * language in question. - */ - - switch (PRIMARYLANGID (LOWORD (ime))) - { - case LANG_JAPANESE: - lang = "ja"; break; - case LANG_KOREAN: - lang = "ko"; break; - case LANG_CHINESE: - switch (SUBLANGID (LOWORD (ime))) - { - case SUBLANG_CHINESE_TRADITIONAL: - lang = "zh_TW"; break; - case SUBLANG_CHINESE_SIMPLIFIED: - lang = "zh_CN"; break; - case SUBLANG_CHINESE_HONGKONG: - lang = "zh_HK"; break; - case SUBLANG_CHINESE_SINGAPORE: - lang = "zh_SG"; break; - case SUBLANG_CHINESE_MACAU: - lang = "zh_MO"; break; - default: - lang = "zh"; break; - } - break; - default: - lang = ""; break; - } - - style = gtk_widget_get_style_context (widget); - gtk_style_context_save (style); - gtk_style_context_set_state (style, GTK_STATE_FLAG_NORMAL); - gtk_style_context_get (style, - "font", - &font_desc, - NULL); - gtk_style_context_restore (style); - - if (lang[0]) - { - /* We know what language it is. Look for a character, any - * character, that language needs. - */ - PangoLanguage *pango_lang = pango_language_from_string (lang); - PangoFontset *fontset = - pango_context_load_fontset (pango_context, - font_desc, - pango_lang); - gunichar *sample = - g_utf8_to_ucs4 (pango_language_get_sample_string (pango_lang), - -1, NULL, NULL, NULL); - wc = 0x4E00; /* In all CJK languages? */ - if (sample != NULL) - { - int i; - - for (i = 0; sample[i]; i++) - if (g_unichar_iswide (sample[i])) - { - wc = sample[i]; - break; - } - g_free (sample); - } - font = pango_fontset_get_font (fontset, wc); - g_object_unref (fontset); - } - else - font = pango_context_load_font (pango_context, font_desc); - - if (!font) - goto ERROR_OUT; - - logfont = pango_win32_font_logfont (font); - if (logfont) - ImmSetCompositionFont (himc, logfont); - - g_object_unref (font); - -ERROR_OUT: - /* clean */ - ImmReleaseContext (hwnd, himc); -} - - -static GdkFilterReturn -gtk_im_context_ime_message_filter (GdkXEvent *xevent, - GdkEvent *event, - gpointer data) -{ - GtkIMContext *context; - GtkIMContextIME *context_ime; - HWND hwnd; - HIMC himc; - MSG *msg = (MSG *) xevent; - GdkFilterReturn retval = GDK_FILTER_CONTINUE; - - g_return_val_if_fail (GTK_IS_IM_CONTEXT_IME (data), retval); - - context = GTK_IM_CONTEXT (data); - context_ime = GTK_IM_CONTEXT_IME (data); - if (!context_ime->focus) - return retval; - - hwnd = gdk_win32_window_get_impl_hwnd (context_ime->client_window); - himc = ImmGetContext (hwnd); - if (!himc) - return retval; - - switch (msg->message) - { - case WM_IME_COMPOSITION: - { - gint wx = 0, wy = 0; - CANDIDATEFORM cf; - - get_window_position (context_ime->client_window, &wx, &wy); - /* FIXME! */ - { - HWND hwnd_top; - POINT pt; - RECT rc; - - hwnd_top = - gdk_win32_window_get_impl_hwnd (gdk_window_get_toplevel - (context_ime->client_window)); - GetWindowRect (hwnd_top, &rc); - pt.x = wx; - pt.y = wy; - ClientToScreen (hwnd_top, &pt); - wx = pt.x - rc.left; - wy = pt.y - rc.top; - } - cf.dwIndex = 0; - cf.dwStyle = CFS_CANDIDATEPOS; - cf.ptCurrentPos.x = wx + context_ime->cursor_location.x; - cf.ptCurrentPos.y = wy + context_ime->cursor_location.y - + context_ime->cursor_location.height; - ImmSetCandidateWindow (himc, &cf); - - if ((msg->lParam & GCS_COMPSTR)) - g_signal_emit_by_name (context, "preedit-changed"); - - if (msg->lParam & GCS_RESULTSTR) - { - gsize len; - gchar *utf8str = NULL; - GError *error = NULL; - - len = ImmGetCompositionStringW (himc, GCS_RESULTSTR, NULL, 0); - - if (len > 0) - { - gpointer buf = g_alloca (len); - ImmGetCompositionStringW (himc, GCS_RESULTSTR, buf, len); - len /= 2; - context_ime->commit_string = g_utf16_to_utf8 (buf, len, NULL, NULL, &error); - if (error) - { - g_warning ("%s", error->message); - g_error_free (error); - } - } - - if (context_ime->commit_string) - retval = TRUE; - } - - if (context_ime->use_preedit) - retval = TRUE; - break; - } - - case WM_IME_STARTCOMPOSITION: - context_ime->preediting = TRUE; - gtk_im_context_ime_set_cursor_location (context, NULL); - g_signal_emit_by_name (context, "preedit-start"); - if (context_ime->use_preedit) - retval = TRUE; - break; - - case WM_IME_ENDCOMPOSITION: - context_ime->preediting = FALSE; - g_signal_emit_by_name (context, "preedit-changed"); - g_signal_emit_by_name (context, "preedit-end"); - - if (context_ime->commit_string) - { - g_signal_emit_by_name (context, "commit", context_ime->commit_string); - g_free (context_ime->commit_string); - context_ime->commit_string = NULL; - } - - if (context_ime->use_preedit) - retval = TRUE; - break; - - case WM_IME_NOTIFY: - switch (msg->wParam) - { - case IMN_SETOPENSTATUS: - context_ime->opened = ImmGetOpenStatus (himc); - gtk_im_context_ime_set_preedit_font (context); - break; - - default: - break; - } - - default: - break; - } - - ImmReleaseContext (hwnd, himc); - return retval; -} - - -/* - * x and y must be initialized to 0. - */ -static void -get_window_position (GdkWindow *win, gint *x, gint *y) -{ - GdkWindow *parent, *toplevel; - gint wx, wy; - - g_return_if_fail (GDK_IS_WINDOW (win)); - g_return_if_fail (x && y); - - gdk_window_get_position (win, &wx, &wy); - *x += wx; - *y += wy; - parent = gdk_window_get_parent (win); - toplevel = gdk_window_get_toplevel (win); - - if (parent && parent != toplevel) - get_window_position (parent, x, y); -} - - -/* - * probably, this handler isn't needed. - */ -static void -cb_client_widget_hierarchy_changed (GtkWidget *widget, - GtkWidget *widget2, - GtkIMContextIME *context_ime) -{ - GdkWindow *new_toplevel; - - g_return_if_fail (GTK_IS_WIDGET (widget)); - g_return_if_fail (GTK_IS_IM_CONTEXT_IME (context_ime)); - - if (!context_ime->client_window) - return; - if (!context_ime->focus) - return; - - new_toplevel = gdk_window_get_toplevel (context_ime->client_window); - if (context_ime->toplevel == new_toplevel) - return; - - /* remove filter from old toplevel */ - if (GDK_IS_WINDOW (context_ime->toplevel)) - { - gdk_window_remove_filter (context_ime->toplevel, - gtk_im_context_ime_message_filter, - context_ime); - } - else - { - } - - /* add filter to new toplevel */ - if (GDK_IS_WINDOW (new_toplevel)) - { - gdk_window_add_filter (new_toplevel, - gtk_im_context_ime_message_filter, context_ime); - } - else - { - } - - context_ime->toplevel = new_toplevel; -} diff --git a/modules/input/gtkimcontextime.h b/modules/input/gtkimcontextime.h deleted file mode 100644 index 6bb036558f..0000000000 --- a/modules/input/gtkimcontextime.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * gtkimmoduleime - * Copyright (C) 2003 Takuro Ashie - * Copyright (C) 2003 Kazuki IWAMOTO - * - * 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 <gtk/gtk.h> - -#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)) -#define GTK_IS_IM_CONTEXT_IME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_IM_CONTEXT_IME)) -#define GTK_IS_IM_CONTEXT_IME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_IM_CONTEXT_IME)) -#define GTK_IM_CONTEXT_IME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_IM_CONTEXT_IME, GtkIMContextIMEClass)) - -typedef struct _GtkIMContextIME GtkIMContextIME; -typedef struct _GtkIMContextIMEPrivate GtkIMContextIMEPrivate; -typedef struct _GtkIMContextIMEClass GtkIMContextIMEClass; - -struct _GtkIMContextIME -{ - GtkIMContext object; - - GdkWindow *client_window; - GdkWindow *toplevel; - guint use_preedit : 1; - guint preediting : 1; - guint opened : 1; - guint focus : 1; - GdkRectangle cursor_location; - gchar *commit_string; - - GtkIMContextIMEPrivate *priv; -}; - -struct _GtkIMContextIMEClass -{ - GtkIMContextClass parent_class; -}; - - -void gtk_im_context_ime_register_type (GTypeModule * type_module); -GtkIMContext *gtk_im_context_ime_new (void); diff --git a/modules/input/gtkimcontextxim.c b/modules/input/gtkimcontextxim.c deleted file mode 100644 index 03ce3e727c..0000000000 --- a/modules/input/gtkimcontextxim.c +++ /dev/null @@ -1,1804 +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 "locale.h" -#include <string.h> -#include <stdlib.h> - -#include "gtkimmodule.h" -#include "gtkimcontextxim.h" - -#include "gtk/gtkintl.h" - -typedef struct _StatusWindow StatusWindow; -typedef struct _GtkXIMInfo GtkXIMInfo; - -struct _GtkIMContextXIM -{ - GtkIMContext object; - - GtkXIMInfo *im_info; - - gchar *locale; - gchar *mb_charset; - - GdkWindow *client_window; - Window client_window_xid; - GtkWidget *client_widget; - - /* The status window for this input context; we claim the - * status window when we are focused and have created an XIC - */ - StatusWindow *status_window; - - gint preedit_size; - gint preedit_length; - gunichar *preedit_chars; - XIMFeedback *feedbacks; - - gint preedit_cursor; - - XIMCallback preedit_start_callback; - XIMCallback preedit_done_callback; - XIMCallback preedit_draw_callback; - XIMCallback preedit_caret_callback; - - XIMCallback status_start_callback; - XIMCallback status_done_callback; - XIMCallback status_draw_callback; - - XIMCallback string_conversion_callback; - - XIC ic; - - guint filter_key_release : 1; - guint use_preedit : 1; - guint finalizing : 1; - guint in_toplevel : 1; - guint has_focus : 1; -}; - -struct _GtkXIMInfo -{ - GdkDisplay *display; - XIM im; - char *locale; - XIMStyle preedit_style_setting; - XIMStyle status_style_setting; - XIMStyle style; - GtkSettings *settings; - gulong status_set; - gulong preedit_set; - gulong display_closed_cb; - XIMStyles *xim_styles; - GSList *ics; - - guint reconnecting :1; - guint supports_string_conversion; -}; - -/* A context status window; these are kept in the status_windows list. */ -struct _StatusWindow -{ - GtkWidget *window; - - /* Toplevel window to which the status window corresponds */ - GtkWidget *toplevel; - - /* Currently focused GtkIMContextXIM for the toplevel, if any */ - GtkIMContextXIM *context; -}; - -static void gtk_im_context_xim_class_init (GtkIMContextXIMClass *class); -static void gtk_im_context_xim_init (GtkIMContextXIM *im_context_xim); -static void gtk_im_context_xim_finalize (GObject *obj); -static void gtk_im_context_xim_set_client_widget (GtkIMContext *context, - GtkWidget *widget); -static gboolean gtk_im_context_xim_filter_keypress (GtkIMContext *context, - GdkEventKey *key); -static void gtk_im_context_xim_reset (GtkIMContext *context); -static void gtk_im_context_xim_focus_in (GtkIMContext *context); -static void gtk_im_context_xim_focus_out (GtkIMContext *context); -static void gtk_im_context_xim_set_cursor_location (GtkIMContext *context, - GdkRectangle *area); -static void gtk_im_context_xim_set_use_preedit (GtkIMContext *context, - gboolean use_preedit); -static void gtk_im_context_xim_get_preedit_string (GtkIMContext *context, - gchar **str, - PangoAttrList **attrs, - gint *cursor_pos); - -static void reinitialize_ic (GtkIMContextXIM *context_xim); -static void set_ic_client_window (GtkIMContextXIM *context_xim, - GdkWindow *client_window); - -static void setup_styles (GtkXIMInfo *info); - -static void update_client_widget (GtkIMContextXIM *context_xim); -static void update_status_window (GtkIMContextXIM *context_xim); - -static StatusWindow *status_window_get (GtkWidget *toplevel); -static void status_window_free (StatusWindow *status_window); -static void status_window_set_text (StatusWindow *status_window, - const gchar *text); - -static void xim_destroy_callback (XIM xim, - XPointer client_data, - XPointer call_data); - -static XIC gtk_im_context_xim_get_ic (GtkIMContextXIM *context_xim); -static void xim_info_display_closed (GdkDisplay *display, - gboolean is_error, - GtkXIMInfo *info); - -G_DEFINE_DYNAMIC_TYPE (GtkIMContextXIM, gtk_im_context_xim, GTK_TYPE_IM_CONTEXT) - -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; - -#define PREEDIT_MASK (XIMPreeditCallbacks | XIMPreeditPosition | \ - XIMPreeditArea | XIMPreeditNothing | XIMPreeditNone) -#define STATUS_MASK (XIMStatusCallbacks | XIMStatusArea | \ - XIMStatusNothing | XIMStatusNone) -#define ALLOWED_MASK (XIMPreeditCallbacks | XIMPreeditNothing | XIMPreeditNone | \ - XIMStatusCallbacks | XIMStatusNothing | XIMStatusNone) - -static XIMStyle -choose_better_style (XIMStyle style1, XIMStyle style2) -{ - XIMStyle s1, s2, u; - - if (style1 == 0) return style2; - if (style2 == 0) return style1; - if ((style1 & (PREEDIT_MASK | STATUS_MASK)) - == (style2 & (PREEDIT_MASK | STATUS_MASK))) - return style1; - - s1 = style1 & PREEDIT_MASK; - s2 = style2 & PREEDIT_MASK; - u = s1 | s2; - if (s1 != s2) { - if (u & XIMPreeditCallbacks) - return (s1 == XIMPreeditCallbacks) ? style1 : style2; - else if (u & XIMPreeditPosition) - return (s1 == XIMPreeditPosition) ? style1 :style2; - else if (u & XIMPreeditArea) - return (s1 == XIMPreeditArea) ? style1 : style2; - else if (u & XIMPreeditNothing) - return (s1 == XIMPreeditNothing) ? style1 : style2; - else if (u & XIMPreeditNone) - return (s1 == XIMPreeditNone) ? style1 : style2; - } else { - s1 = style1 & STATUS_MASK; - s2 = style2 & STATUS_MASK; - u = s1 | s2; - if (u & XIMStatusCallbacks) - return (s1 == XIMStatusCallbacks) ? style1 : style2; - else if (u & XIMStatusArea) - return (s1 == XIMStatusArea) ? style1 : style2; - else if (u & XIMStatusNothing) - return (s1 == XIMStatusNothing) ? style1 : style2; - else if (u & XIMStatusNone) - return (s1 == XIMStatusNone) ? style1 : style2; - } - return 0; /* Get rid of stupid warning */ -} - -static void -reinitialize_all_ics (GtkXIMInfo *info) -{ - GSList *tmp_list; - - for (tmp_list = info->ics; tmp_list; tmp_list = tmp_list->next) - reinitialize_ic (tmp_list->data); -} - -static void -setup_styles (GtkXIMInfo *info) -{ - int i; - unsigned long settings_preference; - XIMStyles *xim_styles = info->xim_styles; - - settings_preference = info->status_style_setting|info->preedit_style_setting; - info->style = 0; - if (xim_styles) - { - for (i = 0; i < xim_styles->count_styles; i++) - if ((xim_styles->supported_styles[i] & ALLOWED_MASK) == xim_styles->supported_styles[i]) - { - if (settings_preference == xim_styles->supported_styles[i]) - { - info->style = settings_preference; - break; - } - info->style = choose_better_style (info->style, - xim_styles->supported_styles[i]); - } - } - if (info->style == 0) - info->style = XIMPreeditNothing | XIMStatusNothing; -} - -static void -setup_im (GtkXIMInfo *info) -{ - XIMValuesList *ic_values = NULL; - XIMCallback im_destroy_callback; - GdkDisplay *display; - - if (info->im == NULL) - return; - - im_destroy_callback.client_data = (XPointer)info; - im_destroy_callback.callback = (XIMProc)xim_destroy_callback; - XSetIMValues (info->im, - XNDestroyCallback, &im_destroy_callback, - NULL); - - XGetIMValues (info->im, - XNQueryInputStyle, &info->xim_styles, - XNQueryICValuesList, &ic_values, - NULL); - - info->supports_string_conversion = FALSE; - if (ic_values) - { - int i; - - for (i = 0; i < ic_values->count_values; i++) - if (strcmp (ic_values->supported_values[i], - XNStringConversionCallback) == 0) - { - info->supports_string_conversion = TRUE; - break; - } - -#if 0 - for (i = 0; i < ic_values->count_values; i++) - g_print ("%s\n", ic_values->supported_values[i]); - for (i = 0; i < xim_styles->count_styles; i++) - g_print ("%#x\n", xim_styles->supported_styles[i]); -#endif - - XFree (ic_values); - } - - info->status_style_setting = XIMStatusCallbacks; - info->preedit_style_setting = XIMPreeditCallbacks; - setup_styles (info); - reinitialize_all_ics (info); - - display = info->display; - info->display_closed_cb = g_signal_connect (display, "closed", - G_CALLBACK (xim_info_display_closed), info); -} - -static void -xim_info_display_closed (GdkDisplay *display, - gboolean is_error, - GtkXIMInfo *info) -{ - GSList *ics, *tmp_list; - - open_ims = g_slist_remove (open_ims, info); - - ics = info->ics; - info->ics = NULL; - - for (tmp_list = ics; tmp_list; tmp_list = tmp_list->next) - set_ic_client_window (tmp_list->data, NULL); - - g_slist_free (ics); - - if (info->status_set) - g_signal_handler_disconnect (info->settings, info->status_set); - if (info->preedit_set) - g_signal_handler_disconnect (info->settings, info->preedit_set); - if (info->display_closed_cb) - g_signal_handler_disconnect (display, info->display_closed_cb); - - if (info->xim_styles) - XFree (info->xim_styles); - g_free (info->locale); - - if (info->im) - XCloseIM (info->im); - - g_free (info); -} - -static void -xim_instantiate_callback (Display *display, XPointer client_data, - XPointer call_data) -{ - GtkXIMInfo *info = (GtkXIMInfo*)client_data; - XIM im = NULL; - - im = XOpenIM (display, NULL, NULL, NULL); - - if (!im) - return; - - info->im = im; - setup_im (info); - - XUnregisterIMInstantiateCallback (display, NULL, NULL, NULL, - xim_instantiate_callback, - (XPointer)info); - info->reconnecting = FALSE; -} - -/* initialize info->im */ -static void -xim_info_try_im (GtkXIMInfo *info) -{ - GdkDisplay *display = info->display; - - g_assert (info->im == NULL); - if (info->reconnecting) - return; - - if (XSupportsLocale ()) - { - if (!XSetLocaleModifiers ("")) - g_warning ("Unable to set locale modifiers with XSetLocaleModifiers()"); - info->im = XOpenIM (GDK_DISPLAY_XDISPLAY (display), NULL, NULL, NULL); - if (!info->im) - { - XRegisterIMInstantiateCallback (GDK_DISPLAY_XDISPLAY(display), - NULL, NULL, NULL, - xim_instantiate_callback, - (XPointer)info); - info->reconnecting = TRUE; - return; - } - setup_im (info); - } -} - -static void -xim_destroy_callback (XIM xim, - XPointer client_data, - XPointer call_data) -{ - GtkXIMInfo *info = (GtkXIMInfo*)client_data; - - info->im = NULL; - - g_signal_handler_disconnect (info->settings, info->status_set); - info->status_set = 0; - g_signal_handler_disconnect (info->settings, info->preedit_set); - info->preedit_set = 0; - - reinitialize_all_ics (info); - xim_info_try_im (info); - return; -} - -static GtkXIMInfo * -get_im (GdkWindow *client_window, - const char *locale) -{ - GSList *tmp_list; - GtkXIMInfo *info; - GdkDisplay *display = gdk_window_get_display (client_window); - - info = NULL; - tmp_list = open_ims; - while (tmp_list) - { - GtkXIMInfo *tmp_info = tmp_list->data; - if (tmp_info->display == display && - strcmp (tmp_info->locale, locale) == 0) - { - if (tmp_info->im) - { - return tmp_info; - } - else - { - tmp_info = tmp_info; - break; - } - } - tmp_list = tmp_list->next; - } - - if (info == NULL) - { - info = g_new (GtkXIMInfo, 1); - open_ims = g_slist_prepend (open_ims, info); - - info->display = display; - info->locale = g_strdup (locale); - info->xim_styles = NULL; - info->preedit_style_setting = 0; - info->status_style_setting = 0; - info->settings = NULL; - info->preedit_set = 0; - info->status_set = 0; - info->display_closed_cb = 0; - info->ics = NULL; - info->reconnecting = FALSE; - info->im = NULL; - } - - xim_info_try_im (info); - return info; -} - -static void -gtk_im_context_xim_class_init (GtkIMContextXIMClass *class) -{ - GtkIMContextClass *im_context_class = GTK_IM_CONTEXT_CLASS (class); - GObjectClass *gobject_class = G_OBJECT_CLASS (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; - im_context_class->get_preedit_string = gtk_im_context_xim_get_preedit_string; - im_context_class->focus_in = gtk_im_context_xim_focus_in; - im_context_class->focus_out = gtk_im_context_xim_focus_out; - im_context_class->set_cursor_location = gtk_im_context_xim_set_cursor_location; - im_context_class->set_use_preedit = gtk_im_context_xim_set_use_preedit; - 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) -{ - im_context_xim->use_preedit = TRUE; - im_context_xim->filter_key_release = FALSE; - im_context_xim->finalizing = FALSE; - im_context_xim->has_focus = FALSE; - im_context_xim->in_toplevel = FALSE; -} - -static void -gtk_im_context_xim_finalize (GObject *obj) -{ - GtkIMContextXIM *context_xim = GTK_IM_CONTEXT_XIM (obj); - - context_xim->finalizing = TRUE; - - if (context_xim->im_info && !context_xim->im_info->ics->next) - { - if (context_xim->im_info->reconnecting) - { - GdkDisplay *display; - - display = context_xim->im_info->display; - XUnregisterIMInstantiateCallback (GDK_DISPLAY_XDISPLAY (display), - NULL, NULL, NULL, - xim_instantiate_callback, - (XPointer)context_xim->im_info); - } - else if (context_xim->im_info->im) - { - XIMCallback im_destroy_callback; - - im_destroy_callback.client_data = NULL; - im_destroy_callback.callback = NULL; - XSetIMValues (context_xim->im_info->im, - XNDestroyCallback, &im_destroy_callback, - NULL); - } - } - - set_ic_client_window (context_xim, NULL); - - g_free (context_xim->locale); - g_free (context_xim->mb_charset); - - G_OBJECT_CLASS (gtk_im_context_xim_parent_class)->finalize (obj); -} - -static void -reinitialize_ic (GtkIMContextXIM *context_xim) -{ - if (context_xim->ic) - { - XDestroyIC (context_xim->ic); - context_xim->ic = NULL; - update_status_window (context_xim); - - if (context_xim->preedit_length) - { - context_xim->preedit_length = 0; - if (!context_xim->finalizing) - g_signal_emit_by_name (context_xim, "preedit-changed"); - } - } - /* - reset filter_key_release flag, otherwise keystrokes will be doubled - until reconnecting to XIM. - */ - context_xim->filter_key_release = FALSE; -} - -static void -set_ic_client_window (GtkIMContextXIM *context_xim, - GdkWindow *client_window) -{ - reinitialize_ic (context_xim); - if (context_xim->client_window) - { - context_xim->im_info->ics = g_slist_remove (context_xim->im_info->ics, context_xim); - context_xim->im_info = NULL; - } - - context_xim->client_window = client_window; - context_xim->client_window_xid = None; - - if (context_xim->client_window) - { - GdkWindow *native; - - context_xim->im_info = get_im (context_xim->client_window, context_xim->locale); - context_xim->im_info->ics = g_slist_prepend (context_xim->im_info->ics, context_xim); - - for (native = client_window; native; native = gdk_window_get_parent (native)) - { - if (gdk_window_has_native (native)) - { - context_xim->client_window_xid = gdk_x11_window_get_xid (native); - break; - } - } - } - - update_client_widget (context_xim); -} - -static void -gtk_im_context_xim_set_client_widget (GtkIMContext *context, - GtkWidget *widget) -{ - GtkIMContextXIM *context_xim = GTK_IM_CONTEXT_XIM (context); - GtkWidget *toplevel = gtk_widget_get_toplevel (widget); - - set_ic_client_window (context_xim, gtk_widget_get_window (toplevel)); -} - -GtkIMContext * -gtk_im_context_xim_new (void) -{ - GtkIMContextXIM *result; - const gchar *charset; - - if (!GDK_IS_X11_DISPLAY(gdk_display_get_default())) - return NULL; - result = g_object_new (GTK_TYPE_IM_CONTEXT_XIM, NULL); - - result->locale = g_strdup (setlocale (LC_CTYPE, NULL)); - - g_get_charset (&charset); - result->mb_charset = g_strdup (charset); - - return GTK_IM_CONTEXT (result); -} - -static char * -mb_to_utf8 (GtkIMContextXIM *context_xim, - const char *str) -{ - GError *error = NULL; - gchar *result; - - if (strcmp (context_xim->mb_charset, "UTF-8") == 0) - result = g_strdup (str); - else - { - result = g_convert (str, -1, - "UTF-8", context_xim->mb_charset, - NULL, NULL, &error); - if (!result) - { - g_warning ("Error converting text from IM to UTF-8: %s\n", error->message); - g_error_free (error); - } - } - - return result; -} - -static gboolean -gtk_im_context_xim_filter_keypress (GtkIMContext *context, - GdkEventKey *event) -{ - GtkIMContextXIM *context_xim = GTK_IM_CONTEXT_XIM (context); - XIC ic = gtk_im_context_xim_get_ic (context_xim); - gchar static_buffer[256]; - gchar *buffer = static_buffer; - gint buffer_size = sizeof(static_buffer) - 1; - gint num_bytes = 0; - KeySym keysym; - Status status; - gboolean result = FALSE; - GdkWindow *window; - XKeyPressedEvent xevent; - GdkEventType event_type; - guint state; - - event_type = gdk_event_get_event_type ((GdkEvent *) event); - - if (!gdk_event_get_state ((GdkEvent *) event, &state)) - return GDK_EVENT_PROPAGATE; - - if (event_type == GDK_KEY_RELEASE && !context_xim->filter_key_release) - return FALSE; - - window = gdk_window_get_toplevel (gdk_event_get_window ((GdkEvent *) event)); - - xevent.type = (event_type == GDK_KEY_PRESS) ? KeyPress : KeyRelease; - xevent.serial = 0; /* hope it doesn't matter */ - xevent.send_event = gdk_event_is_sent ((GdkEvent *)event); - xevent.display = GDK_WINDOW_XDISPLAY (window); - xevent.window = GDK_WINDOW_XID (window); - xevent.root = DefaultRootWindow(GDK_WINDOW_XDISPLAY (window)); - xevent.subwindow = xevent.window; - xevent.time = gdk_event_get_time ((GdkEvent *) event); - xevent.x = xevent.x_root = 0; - xevent.y = xevent.y_root = 0; - xevent.state = state; - xevent.keycode = gdk_event_get_scancode ((GdkEvent *) event); - xevent.same_screen = True; - - if (XFilterEvent ((XEvent *)&xevent, context_xim->client_window_xid)) - return TRUE; - - if (state & - (gtk_accelerator_get_default_mod_mask () & ~(GDK_SHIFT_MASK | GDK_CONTROL_MASK))) - return FALSE; - - again: - if (ic) - num_bytes = XmbLookupString (ic, &xevent, buffer, buffer_size, &keysym, &status); - else - { - num_bytes = XLookupString (&xevent, buffer, buffer_size, &keysym, NULL); - status = XLookupBoth; - } - - if (status == XBufferOverflow) - { - buffer_size = num_bytes; - if (buffer != static_buffer) - g_free (buffer); - buffer = g_malloc (num_bytes + 1); - goto again; - } - - /* I don't know how we should properly handle XLookupKeysym or XLookupBoth - * here ... do input methods actually change the keysym? we can't really - * feed it back to accelerator processing at this point... - */ - if (status == XLookupChars || status == XLookupBoth) - { - char *result_utf8; - - buffer[num_bytes] = '\0'; - - result_utf8 = mb_to_utf8 (context_xim, buffer); - if (result_utf8) - { - if ((guchar)result_utf8[0] >= 0x20 && - result_utf8[0] != 0x7f) /* Some IM have a nasty habit of converting - * control characters into strings - */ - { - g_signal_emit_by_name (context, "commit", result_utf8); - result = TRUE; - } - - g_free (result_utf8); - } - } - - if (buffer != static_buffer) - g_free (buffer); - - return result; -} - -static void -gtk_im_context_xim_focus_in (GtkIMContext *context) -{ - GtkIMContextXIM *context_xim = GTK_IM_CONTEXT_XIM (context); - - if (!context_xim->has_focus) - { - XIC ic = gtk_im_context_xim_get_ic (context_xim); - - context_xim->has_focus = TRUE; - update_status_window (context_xim); - - if (ic) - XSetICFocus (ic); - } - - return; -} - -static void -gtk_im_context_xim_focus_out (GtkIMContext *context) -{ - GtkIMContextXIM *context_xim = GTK_IM_CONTEXT_XIM (context); - - if (context_xim->has_focus) - { - XIC ic = gtk_im_context_xim_get_ic (context_xim); - - context_xim->has_focus = FALSE; - update_status_window (context_xim); - - if (ic) - XUnsetICFocus (ic); - } - - return; -} - -static void -gtk_im_context_xim_set_cursor_location (GtkIMContext *context, - GdkRectangle *area) -{ - GtkIMContextXIM *context_xim = GTK_IM_CONTEXT_XIM (context); - XIC ic = gtk_im_context_xim_get_ic (context_xim); - - XVaNestedList preedit_attr; - XPoint spot; - - if (!ic) - return; - - spot.x = area->x; - spot.y = area->y + area->height; - - preedit_attr = XVaCreateNestedList (0, - XNSpotLocation, &spot, - NULL); - XSetICValues (ic, - XNPreeditAttributes, preedit_attr, - NULL); - XFree(preedit_attr); - - return; -} - -static void -gtk_im_context_xim_set_use_preedit (GtkIMContext *context, - gboolean use_preedit) -{ - GtkIMContextXIM *context_xim = GTK_IM_CONTEXT_XIM (context); - - use_preedit = use_preedit != FALSE; - - if (context_xim->use_preedit != use_preedit) - { - context_xim->use_preedit = use_preedit; - reinitialize_ic (context_xim); - } - - return; -} - -static void -gtk_im_context_xim_reset (GtkIMContext *context) -{ - GtkIMContextXIM *context_xim = GTK_IM_CONTEXT_XIM (context); - XIC ic = gtk_im_context_xim_get_ic (context_xim); - gchar *result; - - /* restore conversion state after resetting ic later */ - XIMPreeditState preedit_state = XIMPreeditUnKnown; - XVaNestedList preedit_attr; - gboolean have_preedit_state = FALSE; - - if (!ic) - return; - - - if (context_xim->preedit_length == 0) - return; - - preedit_attr = XVaCreateNestedList(0, - XNPreeditState, &preedit_state, - NULL); - if (!XGetICValues(ic, - XNPreeditAttributes, preedit_attr, - NULL)) - have_preedit_state = TRUE; - - XFree(preedit_attr); - - result = XmbResetIC (ic); - - preedit_attr = XVaCreateNestedList(0, - XNPreeditState, preedit_state, - NULL); - if (have_preedit_state) - XSetICValues(ic, - XNPreeditAttributes, preedit_attr, - NULL); - - XFree(preedit_attr); - - if (result) - { - char *result_utf8 = mb_to_utf8 (context_xim, result); - if (result_utf8) - { - g_signal_emit_by_name (context, "commit", result_utf8); - g_free (result_utf8); - } - } - - if (context_xim->preedit_length) - { - context_xim->preedit_length = 0; - g_signal_emit_by_name (context, "preedit-changed"); - } - - XFree (result); -} - -/* Mask of feedback bits that we render - */ -#define FEEDBACK_MASK (XIMReverse | XIMUnderline) - -static void -add_feedback_attr (PangoAttrList *attrs, - const gchar *str, - XIMFeedback feedback, - gint start_pos, - gint end_pos) -{ - PangoAttribute *attr; - - gint start_index = g_utf8_offset_to_pointer (str, start_pos) - str; - gint end_index = g_utf8_offset_to_pointer (str, end_pos) - str; - - if (feedback & XIMUnderline) - { - attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); - attr->start_index = start_index; - attr->end_index = end_index; - - pango_attr_list_change (attrs, attr); - } - - if (feedback & XIMReverse) - { - attr = pango_attr_foreground_new (0xffff, 0xffff, 0xffff); - attr->start_index = start_index; - attr->end_index = end_index; - - pango_attr_list_change (attrs, attr); - - attr = pango_attr_background_new (0, 0, 0); - attr->start_index = start_index; - attr->end_index = end_index; - - pango_attr_list_change (attrs, attr); - } - - if (feedback & ~FEEDBACK_MASK) - g_warning ("Unrendered feedback style: %#lx", feedback & ~FEEDBACK_MASK); -} - -static void -gtk_im_context_xim_get_preedit_string (GtkIMContext *context, - gchar **str, - PangoAttrList **attrs, - gint *cursor_pos) -{ - GtkIMContextXIM *context_xim = GTK_IM_CONTEXT_XIM (context); - gchar *utf8 = g_ucs4_to_utf8 (context_xim->preedit_chars, context_xim->preedit_length, NULL, NULL, NULL); - - if (attrs) - { - int i; - XIMFeedback last_feedback = 0; - gint start = -1; - - *attrs = pango_attr_list_new (); - - for (i = 0; i < context_xim->preedit_length; i++) - { - XIMFeedback new_feedback = context_xim->feedbacks[i] & FEEDBACK_MASK; - if (new_feedback != last_feedback) - { - if (start >= 0) - add_feedback_attr (*attrs, utf8, last_feedback, start, i); - - last_feedback = new_feedback; - start = i; - } - } - - if (start >= 0) - add_feedback_attr (*attrs, utf8, last_feedback, start, i); - } - - if (str) - *str = utf8; - else - g_free (utf8); - - if (cursor_pos) - *cursor_pos = context_xim->preedit_cursor; -} - -static int -preedit_start_callback (XIC xic, - XPointer client_data, - XPointer call_data) -{ - GtkIMContext *context = GTK_IM_CONTEXT (client_data); - GtkIMContextXIM *context_xim = GTK_IM_CONTEXT_XIM (context); - - if (!context_xim->finalizing) - g_signal_emit_by_name (context, "preedit-start"); - - return -1; /* No length limit */ -} - -static void -preedit_done_callback (XIC xic, - XPointer client_data, - XPointer call_data) -{ - GtkIMContext *context = GTK_IM_CONTEXT (client_data); - GtkIMContextXIM *context_xim = GTK_IM_CONTEXT_XIM (context); - - if (context_xim->preedit_length) - { - context_xim->preedit_length = 0; - if (!context_xim->finalizing) - g_signal_emit_by_name (context_xim, "preedit-changed"); - } - - if (!context_xim->finalizing) - g_signal_emit_by_name (context, "preedit-end"); -} - -static gint -xim_text_to_utf8 (GtkIMContextXIM *context, XIMText *xim_text, gchar **text) -{ - gint text_length = 0; - GError *error = NULL; - gchar *result = NULL; - - if (xim_text && xim_text->string.multi_byte) - { - if (xim_text->encoding_is_wchar) - { - g_warning ("Wide character return from Xlib not currently supported"); - *text = NULL; - return 0; - } - - if (strcmp (context->mb_charset, "UTF-8") == 0) - result = g_strdup (xim_text->string.multi_byte); - else - result = g_convert (xim_text->string.multi_byte, - -1, - "UTF-8", - context->mb_charset, - NULL, NULL, &error); - - if (result) - { - text_length = g_utf8_strlen (result, -1); - - if (text_length != xim_text->length) - { - g_warning ("Size mismatch when converting text from input method: supplied length = %d\n, result length = %d", xim_text->length, text_length); - } - } - else - { - g_warning ("Error converting text from IM to UCS-4: %s", error->message); - g_error_free (error); - - *text = NULL; - return 0; - } - - *text = result; - return text_length; - } - else - { - *text = NULL; - return 0; - } -} - -static void -preedit_draw_callback (XIC xic, - XPointer client_data, - XIMPreeditDrawCallbackStruct *call_data) -{ - GtkIMContextXIM *context = GTK_IM_CONTEXT_XIM (client_data); - - XIMText *new_xim_text = call_data->text; - gint new_text_length; - gunichar *new_text = NULL; - gint i; - gint diff; - gint new_length; - gchar *tmp; - - gint chg_first = CLAMP (call_data->chg_first, 0, context->preedit_length); - gint chg_length = CLAMP (call_data->chg_length, 0, context->preedit_length - chg_first); - - context->preedit_cursor = call_data->caret; - - if (chg_first != call_data->chg_first || chg_length != call_data->chg_length) - g_warning ("Invalid change to preedit string, first=%d length=%d (orig length == %d)", - call_data->chg_first, call_data->chg_length, context->preedit_length); - - new_text_length = xim_text_to_utf8 (context, new_xim_text, &tmp); - if (tmp) - { - new_text = g_utf8_to_ucs4_fast (tmp, -1, NULL); - g_free (tmp); - } - - diff = new_text_length - chg_length; - new_length = context->preedit_length + diff; - - if (new_length > context->preedit_size) - { - context->preedit_size = new_length; - context->preedit_chars = g_renew (gunichar, context->preedit_chars, new_length); - context->feedbacks = g_renew (XIMFeedback, context->feedbacks, new_length); - } - - if (diff < 0) - { - for (i = chg_first + chg_length ; i < context->preedit_length; i++) - { - context->preedit_chars[i + diff] = context->preedit_chars[i]; - context->feedbacks[i + diff] = context->feedbacks[i]; - } - } - else - { - for (i = context->preedit_length - 1; i >= chg_first + chg_length ; i--) - { - context->preedit_chars[i + diff] = context->preedit_chars[i]; - context->feedbacks[i + diff] = context->feedbacks[i]; - } - } - - for (i = 0; i < new_text_length; i++) - { - context->preedit_chars[chg_first + i] = new_text[i]; - context->feedbacks[chg_first + i] = new_xim_text->feedback[i]; - } - - context->preedit_length += diff; - - g_free (new_text); - - if (!context->finalizing) - g_signal_emit_by_name (context, "preedit-changed"); -} - - -static void -preedit_caret_callback (XIC xic, - XPointer client_data, - XIMPreeditCaretCallbackStruct *call_data) -{ - GtkIMContextXIM *context = GTK_IM_CONTEXT_XIM (client_data); - - if (call_data->direction == XIMAbsolutePosition) - { - context->preedit_cursor = call_data->position; - if (!context->finalizing) - g_signal_emit_by_name (context, "preedit-changed"); - } - else - { - g_warning ("Caret movement command: %d %d %d not supported", - call_data->position, call_data->direction, call_data->style); - } -} - -static void -status_start_callback (XIC xic, - XPointer client_data, - XPointer call_data) -{ - return; -} - -static void -status_done_callback (XIC xic, - XPointer client_data, - XPointer call_data) -{ - return; -} - -static void -status_draw_callback (XIC xic, - XPointer client_data, - XIMStatusDrawCallbackStruct *call_data) -{ - GtkIMContextXIM *context = GTK_IM_CONTEXT_XIM (client_data); - - if (call_data->type == XIMTextType) - { - gchar *text; - xim_text_to_utf8 (context, call_data->data.text, &text); - - if (context->status_window) - status_window_set_text (context->status_window, text ? text : ""); - } - else /* bitmap */ - { - g_print ("Status drawn with bitmap - id = %#lx\n", call_data->data.bitmap); - } -} - -static void -string_conversion_callback (XIC xic, XPointer client_data, XPointer call_data) -{ - GtkIMContextXIM *context_xim; - XIMStringConversionCallbackStruct *conv_data; - gchar *surrounding; - gint cursor_index; - - context_xim = (GtkIMContextXIM *)client_data; - conv_data = (XIMStringConversionCallbackStruct *)call_data; - - if (gtk_im_context_get_surrounding ((GtkIMContext *)context_xim, - &surrounding, &cursor_index)) - { - gchar *text = NULL; - gsize text_len = 0; - gint subst_offset = 0, subst_nchars = 0; - gint i; - gchar *p = surrounding + cursor_index, *q; - gshort position = (gshort)conv_data->position; - - if (position > 0) - { - for (i = position; i > 0 && *p; --i) - p = g_utf8_next_char (p); - if (i > 0) - return; - } - /* According to X11R6.4 Xlib - C Library Reference Manual - * section 13.5.7.3 String Conversion Callback, - * XIMStringConversionPosition is starting position _relative_ - * to current client's cursor position. So it should be able - * to be negative, or referring to a position before the cursor - * would be impossible. But current X protocol defines this as - * unsigned short. So, compiler may warn about the value range - * here. We hope the X protocol is fixed soon. - */ - else if (position < 0) - { - for (i = position; i < 0 && p > surrounding; ++i) - p = g_utf8_prev_char (p); - if (i < 0) - return; - } - - switch (conv_data->direction) - { - case XIMForwardChar: - for (i = conv_data->factor, q = p; i > 0 && *q; --i) - q = g_utf8_next_char (q); - if (i > 0) - break; - text = g_locale_from_utf8 (p, q - p, NULL, &text_len, NULL); - subst_offset = position; - subst_nchars = conv_data->factor; - break; - - case XIMBackwardChar: - for (i = conv_data->factor, q = p; i > 0 && q > surrounding; --i) - q = g_utf8_prev_char (q); - if (i > 0) - break; - text = g_locale_from_utf8 (q, p - q, NULL, &text_len, NULL); - subst_offset = position - conv_data->factor; - subst_nchars = conv_data->factor; - break; - - case XIMForwardWord: - case XIMBackwardWord: - case XIMCaretUp: - case XIMCaretDown: - case XIMNextLine: - case XIMPreviousLine: - case XIMLineStart: - case XIMLineEnd: - case XIMAbsolutePosition: - case XIMDontChange: - default: - break; - } - /* block out any failure happenning to "text", including conversion */ - if (text) - { - conv_data->text = (XIMStringConversionText *) - malloc (sizeof (XIMStringConversionText)); - if (conv_data->text) - { - conv_data->text->length = text_len; - conv_data->text->feedback = NULL; - conv_data->text->encoding_is_wchar = False; - conv_data->text->string.mbs = (char *)malloc (text_len); - if (conv_data->text->string.mbs) - memcpy (conv_data->text->string.mbs, text, text_len); - else - { - free (conv_data->text); - conv_data->text = NULL; - } - } - - g_free (text); - } - if (conv_data->operation == XIMStringConversionSubstitution - && subst_nchars > 0) - { - gtk_im_context_delete_surrounding ((GtkIMContext *)context_xim, - subst_offset, subst_nchars); - } - - g_free (surrounding); - } -} - - -static XVaNestedList -set_preedit_callback (GtkIMContextXIM *context_xim) -{ - context_xim->preedit_start_callback.client_data = (XPointer)context_xim; - context_xim->preedit_start_callback.callback = (XIMProc)preedit_start_callback; - context_xim->preedit_done_callback.client_data = (XPointer)context_xim; - context_xim->preedit_done_callback.callback = (XIMProc)preedit_done_callback; - context_xim->preedit_draw_callback.client_data = (XPointer)context_xim; - context_xim->preedit_draw_callback.callback = (XIMProc)preedit_draw_callback; - context_xim->preedit_caret_callback.client_data = (XPointer)context_xim; - context_xim->preedit_caret_callback.callback = (XIMProc)preedit_caret_callback; - return XVaCreateNestedList (0, - XNPreeditStartCallback, &context_xim->preedit_start_callback, - XNPreeditDoneCallback, &context_xim->preedit_done_callback, - XNPreeditDrawCallback, &context_xim->preedit_draw_callback, - XNPreeditCaretCallback, &context_xim->preedit_caret_callback, - NULL); -} - -static XVaNestedList -set_status_callback (GtkIMContextXIM *context_xim) -{ - context_xim->status_start_callback.client_data = (XPointer)context_xim; - context_xim->status_start_callback.callback = (XIMProc)status_start_callback; - context_xim->status_done_callback.client_data = (XPointer)context_xim; - context_xim->status_done_callback.callback = (XIMProc)status_done_callback; - context_xim->status_draw_callback.client_data = (XPointer)context_xim; - context_xim->status_draw_callback.callback = (XIMProc)status_draw_callback; - - return XVaCreateNestedList (0, - XNStatusStartCallback, &context_xim->status_start_callback, - XNStatusDoneCallback, &context_xim->status_done_callback, - XNStatusDrawCallback, &context_xim->status_draw_callback, - NULL); -} - - -static void -set_string_conversion_callback (GtkIMContextXIM *context_xim, XIC xic) -{ - if (!context_xim->im_info->supports_string_conversion) - return; - - context_xim->string_conversion_callback.client_data = (XPointer)context_xim; - context_xim->string_conversion_callback.callback = (XIMProc)string_conversion_callback; - - XSetICValues (xic, - XNStringConversionCallback, - (XPointer)&context_xim->string_conversion_callback, - NULL); -} - -static XIC -gtk_im_context_xim_get_ic (GtkIMContextXIM *context_xim) -{ - if (context_xim->im_info == NULL || context_xim->im_info->im == NULL) - return NULL; - - if (!context_xim->ic) - { - const char *name1 = NULL; - XVaNestedList list1 = NULL; - const char *name2 = NULL; - XVaNestedList list2 = NULL; - XIMStyle im_style = 0; - XIC xic = NULL; - - if (context_xim->use_preedit && - (context_xim->im_info->style & PREEDIT_MASK) == XIMPreeditCallbacks) - { - im_style |= XIMPreeditCallbacks; - name1 = XNPreeditAttributes; - list1 = set_preedit_callback (context_xim); - } - else if ((context_xim->im_info->style & PREEDIT_MASK) == XIMPreeditNone) - im_style |= XIMPreeditNone; - else - im_style |= XIMPreeditNothing; - - if ((context_xim->im_info->style & STATUS_MASK) == XIMStatusCallbacks) - { - im_style |= XIMStatusCallbacks; - if (name1 == NULL) - { - name1 = XNStatusAttributes; - list1 = set_status_callback (context_xim); - } - else - { - name2 = XNStatusAttributes; - list2 = set_status_callback (context_xim); - } - } - else if ((context_xim->im_info->style & STATUS_MASK) == XIMStatusNone) - im_style |= XIMStatusNone; - else - im_style |= XIMStatusNothing; - - xic = XCreateIC (context_xim->im_info->im, - XNInputStyle, im_style, - XNClientWindow, context_xim->client_window_xid, - name1, list1, - name2, list2, - NULL); - if (list1) - XFree (list1); - if (list2) - XFree (list2); - - if (xic) - { - /* Don't filter key released events with XFilterEvents unless - * input methods ask for. This is a workaround for Solaris input - * method bug in C and European locales. It doubles each key - * stroke if both key pressed and released events are filtered. - * (bugzilla #81759) - */ - gulong mask = 0xaaaaaaaa; - XGetICValues (xic, - XNFilterEvents, &mask, - NULL); - context_xim->filter_key_release = (mask & KeyReleaseMask) != 0; - set_string_conversion_callback (context_xim, xic); - } - - context_xim->ic = xic; - - update_status_window (context_xim); - - if (xic && context_xim->has_focus) - XSetICFocus (xic); - } - return context_xim->ic; -} - -/***************************************************************** - * Status Window handling - * - * A status window is a small window attached to the toplevel - * that is used to display information to the user about the - * current input operation. - * - * We claim the toplevel's status window for an input context if: - * - * A) The input context has a toplevel - * B) The input context has the focus - * C) The input context has an XIC associated with it - * - * Tracking A) and C) is pretty reliable since we - * compute A) and create the XIC for C) ourselves. - * For B) we basically have to depend on our callers - * calling ::focus-in and ::focus-out at the right time. - * - * The toplevel is computed by walking up the GdkWindow - * hierarchy from context->client_window until we find a - * window that is owned by some widget, and then calling - * gtk_widget_get_toplevel() on that widget. This should - * handle both cases where we might have GdkWindows without widgets, - * and cases where GtkWidgets have strange window hierarchies - * (like a torn off GtkHandleBox.) - * - * The status window is visible if and only if there is text - * for it; whenever a new GtkIMContextXIM claims the status - * window, we blank out any existing text. We actually only - * create a GtkWindow for the status window the first time - * it is shown; this is an important optimization when we are - * using XIM with something like a simple compose-key input - * method that never needs a status window. - *****************************************************************/ - -/* Called when we no longer need a status window -*/ -static void -disclaim_status_window (GtkIMContextXIM *context_xim) -{ - if (context_xim->status_window) - { - g_assert (context_xim->status_window->context == context_xim); - - status_window_set_text (context_xim->status_window, ""); - - context_xim->status_window->context = NULL; - context_xim->status_window = NULL; - } -} - -/* Called when we need a status window - */ -static void -claim_status_window (GtkIMContextXIM *context_xim) -{ - if (!context_xim->status_window && context_xim->client_widget) - { - GtkWidget *toplevel = gtk_widget_get_toplevel (context_xim->client_widget); - if (toplevel && gtk_widget_is_toplevel (toplevel)) - { - StatusWindow *status_window = status_window_get (toplevel); - - if (status_window->context) - disclaim_status_window (status_window->context); - - status_window->context = context_xim; - context_xim->status_window = status_window; - } - } -} - -/* Basic call made whenever something changed that might cause - * us to need, or not to need a status window. - */ -static void -update_status_window (GtkIMContextXIM *context_xim) -{ - if (context_xim->ic && context_xim->in_toplevel && context_xim->has_focus) - claim_status_window (context_xim); - else - disclaim_status_window (context_xim); -} - -/* Updates the in_toplevel flag for @context_xim - */ -static void -update_in_toplevel (GtkIMContextXIM *context_xim) -{ - if (context_xim->client_widget) - { - GtkWidget *toplevel = gtk_widget_get_toplevel (context_xim->client_widget); - - context_xim->in_toplevel = (toplevel && gtk_widget_is_toplevel (toplevel)); - } - else - context_xim->in_toplevel = FALSE; - - /* Some paranoia, in case we don't get a focus out */ - if (!context_xim->in_toplevel) - context_xim->has_focus = FALSE; - - update_status_window (context_xim); -} - -/* Callback when @widget's toplevel changes. It will always - * change from NULL to a window, or a window to NULL; - * we use that intermediate NULL state to make sure - * that we disclaim the toplevel status window for the old - * window. - */ -static void -on_client_widget_hierarchy_changed (GtkWidget *widget, - GtkWidget *old_toplevel, - GtkIMContextXIM *context_xim) -{ - update_in_toplevel (context_xim); -} - -/* Finds the GtkWidget that owns the window, or if none, the - * widget owning the nearest parent that has a widget. - */ -static GtkWidget * -widget_for_window (GdkWindow *window) -{ - while (window) - { - gpointer user_data; - gdk_window_get_user_data (window, &user_data); - if (user_data) - return user_data; - - window = gdk_window_get_parent (window); - } - - return NULL; -} - -/* Called when context_xim->client_window changes; takes care of - * removing and/or setting up our watches for the toplevel - */ -static void -update_client_widget (GtkIMContextXIM *context_xim) -{ - GtkWidget *new_client_widget = widget_for_window (context_xim->client_window); - - if (new_client_widget != context_xim->client_widget) - { - if (context_xim->client_widget) - { - g_signal_handlers_disconnect_by_func (context_xim->client_widget, - G_CALLBACK (on_client_widget_hierarchy_changed), - context_xim); - } - context_xim->client_widget = new_client_widget; - if (context_xim->client_widget) - { - g_signal_connect (context_xim->client_widget, "hierarchy-changed", - G_CALLBACK (on_client_widget_hierarchy_changed), - context_xim); - } - - update_in_toplevel (context_xim); - } -} - -/* Called when the toplevel is destroyed; frees the status window - */ -static void -on_status_toplevel_destroy (GtkWidget *toplevel, - StatusWindow *status_window) -{ - status_window_free (status_window); -} - -/* Called when the screen for the toplevel changes; updates the - * screen for the status window to match. - */ -static void -on_status_toplevel_notify_display (GtkWindow *toplevel, - GParamSpec *pspec, - StatusWindow *status_window) -{ - if (status_window->window) - gtk_window_set_display (GTK_WINDOW (status_window->window), - gtk_widget_get_display (GTK_WIDGET (toplevel))); -} - -/* Called when the toplevel window is moved; updates the position of - * the status window to follow it. - */ -static gboolean -on_status_toplevel_configure (GtkWidget *toplevel, - GdkEvent *event, - StatusWindow *status_window) -{ - if (gdk_event_get_event_type (event) == GDK_CONFIGURE) - { - GdkRectangle rect; - GtkRequisition requisition; - gint y; - gint height; - - if (status_window->window) - { - height = DisplayHeight(GDK_WINDOW_XDISPLAY (gtk_widget_get_window (toplevel)), 0); - - gdk_window_get_frame_extents (gtk_widget_get_window (toplevel), &rect); - gtk_widget_get_preferred_size ( (status_window->window), &requisition, NULL); - - if (rect.y + rect.height + requisition.height < height) - y = rect.y + rect.height; - else - y = height - requisition.height; - - gtk_window_move (GTK_WINDOW (status_window->window), rect.x, y); - } - } - - return GDK_EVENT_PROPAGATE; -} - -/* Frees a status window and removes its link from the status_windows list - */ -static void -status_window_free (StatusWindow *status_window) -{ - status_windows = g_slist_remove (status_windows, status_window); - - if (status_window->context) - status_window->context->status_window = NULL; - - g_signal_handlers_disconnect_by_func (status_window->toplevel, - G_CALLBACK (on_status_toplevel_destroy), - status_window); - g_signal_handlers_disconnect_by_func (status_window->toplevel, - G_CALLBACK (on_status_toplevel_notify_display), - status_window); - g_signal_handlers_disconnect_by_func (status_window->toplevel, - G_CALLBACK (on_status_toplevel_configure), - status_window); - - if (status_window->window) - gtk_widget_destroy (status_window->window); - - g_object_set_data (G_OBJECT (status_window->toplevel), "gtk-im-xim-status-window", NULL); - - g_free (status_window); -} - -/* Finds the status window object for a toplevel, creating it if necessary. - */ -static StatusWindow * -status_window_get (GtkWidget *toplevel) -{ - StatusWindow *status_window; - - status_window = g_object_get_data (G_OBJECT (toplevel), "gtk-im-xim-status-window"); - if (status_window) - return status_window; - - status_window = g_new0 (StatusWindow, 1); - status_window->toplevel = toplevel; - - status_windows = g_slist_prepend (status_windows, status_window); - - g_signal_connect (toplevel, "destroy", - G_CALLBACK (on_status_toplevel_destroy), - status_window); - g_signal_connect (toplevel, "event", - G_CALLBACK (on_status_toplevel_configure), - status_window); - g_signal_connect (toplevel, "notify::display", - G_CALLBACK (on_status_toplevel_notify_display), - status_window); - - g_object_set_data (G_OBJECT (toplevel), "gtk-im-xim-status-window", status_window); - - return status_window; -} - -/* Creates the widgets for the status window; called when we - * first need to show text for the status window. - */ -static void -status_window_make_window (StatusWindow *status_window) -{ - GtkWidget *window; - GtkWidget *status_label; - - status_window->window = gtk_window_new (GTK_WINDOW_POPUP); - window = status_window->window; - - gtk_window_set_resizable (GTK_WINDOW (window), FALSE); - - status_label = gtk_label_new (""); - g_object_set (status_label, "margin", 1, NULL); - gtk_widget_show (status_label); - - gtk_container_add (GTK_CONTAINER (window), status_label); - - gtk_window_set_display (GTK_WINDOW (status_window->window), - gtk_widget_get_display (status_window->toplevel)); - - on_status_toplevel_configure (status_window->toplevel, NULL, status_window); -} - -/* Updates the text in the status window, hiding or - * showing the window as necessary. - */ -static void -status_window_set_text (StatusWindow *status_window, - const gchar *text) -{ - if (text[0]) - { - GtkWidget *label; - - if (!status_window->window) - status_window_make_window (status_window); - - label = gtk_bin_get_child (GTK_BIN (status_window->window)); - gtk_label_set_text (GTK_LABEL (label), text); - - gtk_widget_show (status_window->window); - } - else - { - if (status_window->window) - gtk_widget_hide (status_window->window); - } -} - -/** - * gtk_im_context_xim_shutdown: - * - * Destroys all the status windows that are kept by the XIM contexts. This - * function should only be called by the XIM module exit routine. - **/ -void -gtk_im_context_xim_shutdown (void) -{ - while (status_windows) - status_window_free (status_windows->data); - - while (open_ims) - { - GtkXIMInfo *info = open_ims->data; - GdkDisplay *display = info->display; - - xim_info_display_closed (display, FALSE, info); - open_ims = g_slist_remove_link (open_ims, open_ims); - } -} diff --git a/modules/input/gtkimcontextxim.h b/modules/input/gtkimcontextxim.h deleted file mode 100644 index d81a7ff2d1..0000000000 --- a/modules/input/gtkimcontextxim.h +++ /dev/null @@ -1,48 +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_XIM_H__ -#define __GTK_IM_CONTEXT_XIM_H__ - -#include <gtk/gtk.h> -#include "x11/gdkx.h" - -G_BEGIN_DECLS - -#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)) -#define GTK_IS_IM_CONTEXT_XIM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_IM_CONTEXT_XIM)) -#define GTK_IM_CONTEXT_XIM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_IM_CONTEXT_XIM, GtkIMContextXIMClass)) - - -typedef struct _GtkIMContextXIM GtkIMContextXIM; -typedef struct _GtkIMContextXIMClass GtkIMContextXIMClass; - -struct _GtkIMContextXIMClass -{ - GtkIMContextClass parent_class; -}; - -GtkIMContext *gtk_im_context_xim_new (void); - -void gtk_im_context_xim_shutdown (void); - -G_END_DECLS - -#endif /* __GTK_IM_CONTEXT_XIM_H__ */ diff --git a/modules/input/imbroadway.c b/modules/input/imbroadway.c deleted file mode 100644 index 2fb40d471e..0000000000 --- a/modules/input/imbroadway.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * gtkimmodulebroadway - * Copyright (C) 2013 Alexander Larsson - * - * 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/gtk.h> -#include "gtk/gtkintl.h" -#include "gtk/gtkimmodule.h" - -#include "gdk/broadway/gdkbroadway.h" - -#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 -{ - GtkIMContextSimple parent; - GtkWidget *client_widget; -} GtkIMContextBroadway; - -typedef struct _GtkIMContextBroadwayClass -{ - GtkIMContextSimpleClass parent_class; -} GtkIMContextBroadwayClass; - -G_DEFINE_DYNAMIC_TYPE (GtkIMContextBroadway, gtk_im_context_broadway, GTK_TYPE_IM_CONTEXT_SIMPLE) - -void -g_io_module_load (GIOModule *module) -{ - g_type_module_use (G_TYPE_MODULE (module)); - - 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) -{ -} - -char ** -g_io_module_query (void) -{ - char *eps[] = { - GTK_IM_MODULE_EXTENSION_POINT_NAME, - NULL - }; - - return g_strdupv (eps); -} - - -static void -broadway_set_client_widget (GtkIMContext *context, GtkWidget *widget) -{ - GtkIMContextBroadway *bw = GTK_IM_CONTEXT_BROADWAY (context); - - bw->client_widget = widget; -} - -static void -broadway_focus_in (GtkIMContext *context) -{ - GtkIMContextBroadway *bw = GTK_IM_CONTEXT_BROADWAY (context); - GdkDisplay *display; - - if (bw->client_widget) - { - display = gtk_widget_get_display (bw->client_widget); - gdk_broadway_display_show_keyboard (GDK_BROADWAY_DISPLAY (display)); - } -} - -static void -broadway_focus_out (GtkIMContext *context) -{ - GtkIMContextBroadway *bw = GTK_IM_CONTEXT_BROADWAY (context); - GdkDisplay *display; - - if (bw->client_widget) - { - display = gtk_widget_get_display (bw->client_widget); - gdk_broadway_display_hide_keyboard (GDK_BROADWAY_DISPLAY (display)); - } -} - -static void -gtk_im_context_broadway_class_init (GtkIMContextBroadwayClass *class) -{ - GtkIMContextClass *klass = GTK_IM_CONTEXT_CLASS (class); - - klass->focus_in = broadway_focus_in; - klass->focus_out = broadway_focus_out; - klass->set_client_widget = broadway_set_client_widget; -} - -static void -gtk_im_context_broadway_class_finalize (GtkIMContextBroadwayClass *class) -{ -} - -static void -gtk_im_context_broadway_init (GtkIMContextBroadway *im_context) -{ -} diff --git a/modules/input/imm-extra.h b/modules/input/imm-extra.h deleted file mode 100644 index 094dc5b17c..0000000000 --- a/modules/input/imm-extra.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 <windows.h> -#include <imm.h> - - -/* these aren't defined in Cygwin's imm.h */ - -#ifndef WM_IME_REQUEST -# define WM_IME_REQUEST 0x0288 -#endif /* WM_IME_REQUEST */ - -#ifndef IMR_COMPOSITIONWINDOW -# define IMR_COMPOSITIONWINDOW 0x0001 -#endif /* IMR_COMPOSITIONWINDOW */ - -#ifndef IMR_CANDIDATEWINDOW -# define IMR_CANDIDATEWINDOW 0x0002 -#endif /* IMR_CANDIDATEWINDOW */ - -#ifndef IMR_COMPOSITIONFONT -# define IMR_COMPOSITIONFONT 0x0003 -#endif /* IMR_COMPOSITIONFONT */ - -#ifndef IMR_RECONVERTSTRING -# define IMR_RECONVERTSTRING 0x0004 -#endif /* IMR_RECONVERTSTRING */ - -#ifndef IMR_CONFIRMRECONVERTSTRING -# define IMR_CONFIRMRECONVERTSTRING 0x0005 -#endif /* IMR_CONFIRMRECONVERTSTRING */ - -#ifndef IMR_QUERYCHARPOSITION -# define IMR_QUERYCHARPOSITION 0x0006 -typedef struct tagIMECHARPOSITION { - DWORD dwSize; - DWORD dwCharPos; - POINT pt; - UINT cLineHeight; - RECT rcDocument; -} IMECHARPOSITION, *PIMECHARPOSITION; -#endif /* IMR_QUERYCHARPOSITION */ - -#ifndef IMR_DOCUMENTFEED -# define IMR_DOCUMENTFEED 0x0007 -#endif /* IMR_DOCUMENTFEED */ diff --git a/modules/input/imquartz.c b/modules/input/imquartz.c deleted file mode 100644 index 9d1a1cc9f8..0000000000 --- a/modules/input/imquartz.c +++ /dev/null @@ -1,417 +0,0 @@ -/* - * gtkimmodulequartz - * Copyright (C) 2011 Hiroyuki Yamamoto - * - * 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/gtk.h> -#include "gtk/gtkintl.h" -#include "gtk/gtkimmodule.h" - -#include "gdk/quartz/gdkquartz.h" -#include "gdk/quartz/GdkQuartzView.h" - -#define GTK_IM_CONTEXT_TYPE_QUARTZ (type_quartz) -#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; - GtkIMContext *slave; - GdkWindow *client_window; - gchar *preedit_str; - unsigned int cursor_index; - unsigned int selected_len; - GdkRectangle *cursor_rect; - gboolean focused; -} GtkIMContextQuartz; - -typedef struct _GtkIMContextQuartzClass -{ - GtkIMContextClass parent_class; -} GtkIMContextQuartzClass; - -G_DEFINE_DYNAMIC_TYPE (GtkIMContextQuartz, gtk_im_context_quartz, GTK_TYPE_IM_CONTEXT) - -void -g_io_module_load (GIOModule *module) -{ - g_type_module_use (G_TYPE_MODULE (module)); - - 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) -{ -} - -char ** -g_io_module_query (void) -{ - char *eps[] = { - GTK_IM_MODULE_EXTENSION_POINT_NAME, - NULL - }; - - return g_strdupv (eps); -} - - - - - -static void -quartz_get_preedit_string (GtkIMContext *context, - gchar **str, - PangoAttrList **attrs, - gint *cursor_pos) -{ - GtkIMContextQuartz *qc = GTK_IM_CONTEXT_QUARTZ (context); - - GTK_NOTE (MISC, g_print ("quartz_get_preedit_string\n")); - - if (str) - *str = qc->preedit_str ? g_strdup (qc->preedit_str) : g_strdup (""); - - if (attrs) - { - *attrs = pango_attr_list_new (); - int len = g_utf8_strlen (*str, -1); - gchar *ch = *str; - if (len > 0) - { - PangoAttribute *attr; - int i = 0; - for (;;) - { - gchar *s = ch; - ch = g_utf8_next_char (ch); - - if (i >= qc->cursor_index && - i < qc->cursor_index + qc->selected_len) - attr = pango_attr_underline_new (PANGO_UNDERLINE_DOUBLE); - else - attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); - - attr->start_index = s - *str; - if (!*ch) - attr->end_index = attr->start_index + strlen (s); - else - attr->end_index = ch - *str; - - pango_attr_list_change (*attrs, attr); - - if (!*ch) - break; - i++; - } - } - } - if (cursor_pos) - *cursor_pos = qc->cursor_index; -} - -static gboolean -output_result (GtkIMContext *context, - GdkWindow *win) -{ - GtkIMContextQuartz *qc = GTK_IM_CONTEXT_QUARTZ (context); - gboolean retval = FALSE; - gchar *fixed_str, *marked_str; - - fixed_str = g_strdup (g_object_get_data (G_OBJECT (win), TIC_INSERT_TEXT)); - marked_str = g_strdup (g_object_get_data (G_OBJECT (win), TIC_MARKED_TEXT)); - if (fixed_str) - { - GTK_NOTE (MISC, g_print ("tic-insert-text: %s\n", fixed_str)); - g_free (qc->preedit_str); - qc->preedit_str = NULL; - g_object_set_data (G_OBJECT (win), TIC_INSERT_TEXT, NULL); - g_signal_emit_by_name (context, "commit", fixed_str); - g_signal_emit_by_name (context, "preedit_changed"); - - unsigned int filtered = - GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (win), - GIC_FILTER_KEY)); - GTK_NOTE (MISC, g_print ("filtered, %d\n", filtered)); - if (filtered) - retval = TRUE; - else - retval = FALSE; - } - if (marked_str) - { - GTK_NOTE (MISC, g_print ("tic-marked-text: %s\n", marked_str)); - qc->cursor_index = - GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (win), - TIC_SELECTED_POS)); - qc->selected_len = - GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (win), - TIC_SELECTED_LEN)); - g_free (qc->preedit_str); - qc->preedit_str = g_strdup (marked_str); - g_object_set_data (G_OBJECT (win), TIC_MARKED_TEXT, NULL); - g_signal_emit_by_name (context, "preedit_changed"); - retval = TRUE; - } - if (!fixed_str && !marked_str) - { - if (qc->preedit_str && strlen (qc->preedit_str) > 0) - retval = TRUE; - } - g_free (fixed_str); - g_free (marked_str); - return retval; -} - -static gboolean -quartz_filter_keypress (GtkIMContext *context, - GdkEventKey *event) -{ - GtkIMContextQuartz *qc = GTK_IM_CONTEXT_QUARTZ (context); - gboolean retval; - NSView *nsview; - GdkWindow *win; - - GTK_NOTE (MISC, g_print ("quartz_filter_keypress\n")); - - if (!GDK_IS_QUARTZ_WINDOW (qc->client_window)) - return FALSE; - - nsview = gdk_quartz_window_get_nsview (qc->client_window); - win = (GdkWindow *)[ (GdkQuartzView *)nsview gdkWindow]; - GTK_NOTE (MISC, g_print ("client_window: %p, win: %p, nsview: %p\n", - qc->client_window, win, nsview)); - - NSEvent *nsevent = gdk_quartz_event_get_nsevent ((GdkEvent *)event); - - if (!nsevent) - { - if (event->hardware_keycode == 0 && event->keyval == 0xffffff) - /* update text input changes by mouse events */ - return output_result (context, win); - else - return gtk_im_context_filter_keypress (qc->slave, event); - } - - if (event->type == GDK_KEY_RELEASE) - return FALSE; - - if (event->hardware_keycode == 55) /* Command */ - return FALSE; - - NSEventType etype = [nsevent type]; - if (etype == NSKeyDown) - { - g_object_set_data (G_OBJECT (win), TIC_IN_KEY_DOWN, - GUINT_TO_POINTER (TRUE)); - [nsview keyDown: nsevent]; - } - /* JIS_Eisu || JIS_Kana */ - if (event->hardware_keycode == 102 || event->hardware_keycode == 104) - return FALSE; - - retval = output_result(context, win); - g_object_set_data (G_OBJECT (win), TIC_IN_KEY_DOWN, - GUINT_TO_POINTER (FALSE)); - GTK_NOTE (MISC, g_print ("quartz_filter_keypress done\n")); - - return retval; -} - -static void -discard_preedit (GtkIMContext *context) -{ - GtkIMContextQuartz *qc = GTK_IM_CONTEXT_QUARTZ (context); - - if (!qc->client_window) - return; - - if (!GDK_IS_QUARTZ_WINDOW (qc->client_window)) - return; - - NSView *nsview = gdk_quartz_window_get_nsview (qc->client_window); - if (!nsview) - return; - - /* reset any partial input for this NSView */ - [(GdkQuartzView *)nsview unmarkText]; - NSInputManager *currentInputManager = [NSInputManager currentInputManager]; - [currentInputManager markedTextAbandoned:nsview]; - - if (qc->preedit_str && strlen (qc->preedit_str) > 0) - { - g_signal_emit_by_name (context, "commit", qc->preedit_str); - - g_free (qc->preedit_str); - qc->preedit_str = NULL; - g_signal_emit_by_name (context, "preedit_changed"); - } -} - -static void -quartz_reset (GtkIMContext *context) -{ - GTK_NOTE (MISC, g_print ("quartz_reset\n")); - discard_preedit (context); -} - -static void -quartz_set_client_window (GtkIMContext *context, GtkWidget *widget) -{ - GtkIMContextQuartz *qc = GTK_IM_CONTEXT_QUARTZ (context); - - GTK_NOTE (MISC, g_print ("quartz_set_client_window: %p\n", widget)); - - qc->client_window = gtk_widget_get_parent_window (widget); -} - -static void -quartz_focus_in (GtkIMContext *context) -{ - GTK_NOTE (MISC, g_print ("quartz_focus_in\n")); - - GtkIMContextQuartz *qc = GTK_IM_CONTEXT_QUARTZ (context); - qc->focused = TRUE; -} - -static void -quartz_focus_out (GtkIMContext *context) -{ - GTK_NOTE (MISC, g_print ("quartz_focus_out\n")); - - GtkIMContextQuartz *qc = GTK_IM_CONTEXT_QUARTZ (context); - qc->focused = FALSE; - - /* Commit any partially built strings or it'll mess up other GTK+ widgets in the window */ - discard_preedit (context); -} - -static void -quartz_set_cursor_location (GtkIMContext *context, GdkRectangle *area) -{ - GtkIMContextQuartz *qc = GTK_IM_CONTEXT_QUARTZ (context); - gint x, y; - NSView *nsview; - GdkWindow *win; - - GTK_NOTE (MISC, g_print ("quartz_set_cursor_location\n")); - - if (!qc->client_window) - return; - - if (!qc->focused) - return; - - qc->cursor_rect->x = area->x; - qc->cursor_rect->y = area->y; - qc->cursor_rect->width = area->width; - qc->cursor_rect->height = area->height; - - gdk_window_get_origin (qc->client_window, &x, &y); - - qc->cursor_rect->x = area->x + x; - qc->cursor_rect->y = area->y + y; - - if (!GDK_IS_QUARTZ_WINDOW (qc->client_window)) - return; - - nsview = gdk_quartz_window_get_nsview (qc->client_window); - win = (GdkWindow *)[ (GdkQuartzView*)nsview gdkWindow]; - g_object_set_data (G_OBJECT (win), GIC_CURSOR_RECT, qc->cursor_rect); -} - -static void -quartz_set_use_preedit (GtkIMContext *context, gboolean use_preedit) -{ - GTK_NOTE (MISC, g_print ("quartz_set_use_preedit: %d\n", use_preedit)); -} - -static void -commit_cb (GtkIMContext *context, const gchar *str, GtkIMContextQuartz *qc) -{ - g_signal_emit_by_name (qc, "commit", str); -} - -static void -imquartz_finalize (GObject *obj) -{ - GTK_NOTE (MISC, g_print ("imquartz_finalize\n")); - - GtkIMContextQuartz *qc = GTK_IM_CONTEXT_QUARTZ (obj); - g_free (qc->preedit_str); - qc->preedit_str = NULL; - g_free (qc->cursor_rect); - qc->cursor_rect = NULL; - - g_signal_handlers_disconnect_by_func (qc->slave, (gpointer)commit_cb, qc); - g_object_unref (qc->slave); - - gtk_im_context_quartz_parent_class->finalize (obj); -} - -static void -gtk_im_context_quartz_class_init (GtkIMContextQuartzClass *class) -{ - GTK_NOTE (MISC, g_print ("gtk_im_context_quartz_class_init\n")); - - 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; - klass->reset = quartz_reset; - klass->set_client_widget = quartz_set_client_window; - klass->focus_in = quartz_focus_in; - klass->focus_out = quartz_focus_out; - klass->set_cursor_location = quartz_set_cursor_location; - klass->set_use_preedit = quartz_set_use_preedit; - - object_class->finalize = imquartz_finalize; -} - -static void -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")); - - qc->preedit_str = g_strdup (""); - qc->cursor_index = 0; - qc->selected_len = 0; - qc->cursor_rect = g_malloc (sizeof (GdkRectangle)); - qc->focused = FALSE; - - qc->slave = g_object_new (GTK_TYPE_IM_CONTEXT_SIMPLE, NULL); - g_signal_connect (G_OBJECT (qc->slave), "commit", G_CALLBACK (commit_cb), qc); -} diff --git a/modules/input/imwayland.c b/modules/input/imwayland.c deleted file mode 100644 index 24f4f397dd..0000000000 --- a/modules/input/imwayland.c +++ /dev/null @@ -1,655 +0,0 @@ -/* GTK - The GIMP Toolkit - * Copyright (C) 2017 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 <string.h> -#include <wayland-client-protocol.h> - -#include <gtk/gtk.h> -#include "gtk/gtkintl.h" -#include "gtk/gtkimmodule.h" - -#include "gdk/wayland/gdkwayland.h" -#include "gtk-text-input-client-protocol.h" - -typedef struct _GtkIMContextWaylandGlobal GtkIMContextWaylandGlobal; -typedef struct _GtkIMContextWayland GtkIMContextWayland; -typedef struct _GtkIMContextWaylandClass GtkIMContextWaylandClass; - -struct _GtkIMContextWaylandGlobal -{ - struct wl_display *display; - struct wl_registry *registry; - struct gtk_text_input_manager *text_input_manager; - struct gtk_text_input *text_input; - uint32_t enter_serial; - - GtkIMContext *current; -}; - -struct _GtkIMContextWaylandClass -{ - GtkIMContextSimpleClass parent_class; -}; - -struct _GtkIMContextWayland -{ - GtkIMContextSimple parent_instance; - GtkWidget *widget; - - GtkGesture *gesture; - gdouble press_x; - gdouble press_y; - - struct { - gchar *text; - gint cursor_idx; - } surrounding; - - struct { - gchar *text; - gint cursor_idx; - } preedit; - - cairo_rectangle_int_t cursor_rect; - guint use_preedit : 1; -}; - -static GtkIMContextWaylandGlobal *global = NULL; - -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) -{ - g_type_module_use (G_TYPE_MODULE (module)); - - 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) -{ -} - -char ** -g_io_module_query (void) -{ - char *eps[] = { - GTK_IM_MODULE_EXTENSION_POINT_NAME, - NULL - }; - - return g_strdupv (eps); -} - - - -static void -reset_preedit (GtkIMContextWayland *context) -{ - g_clear_pointer (&context->preedit.text, g_free); - context->preedit.cursor_idx = 0; - g_signal_emit_by_name (context, "preedit-changed"); -} - -static void -text_input_enter (void *data, - struct gtk_text_input *text_input, - uint32_t serial, - struct wl_surface *surface) -{ - GtkIMContextWaylandGlobal *global = data; - - global->enter_serial = serial; -} - -static void -text_input_leave (void *data, - struct gtk_text_input *text_input, - uint32_t serial, - struct wl_surface *surface) -{ - GtkIMContextWayland *context; - - if (!global->current) - return; - - context = GTK_IM_CONTEXT_WAYLAND (global->current); - reset_preedit (context); -} - -static void -text_input_preedit (void *data, - struct gtk_text_input *text_input, - const char *text, - guint cursor) -{ - GtkIMContextWayland *context; - gboolean state_change; - - if (!global->current) - return; - - context = GTK_IM_CONTEXT_WAYLAND (global->current); - if (!text && !context->preedit.text) - return; - - state_change = ((text == NULL) != (context->preedit.text == NULL)); - - if (state_change && !context->preedit.text) - g_signal_emit_by_name (context, "preedit-start"); - - g_free (context->preedit.text); - context->preedit.text = g_strdup (text); - context->preedit.cursor_idx = cursor; - - g_signal_emit_by_name (context, "preedit-changed"); - - if (state_change && !context->preedit.text) - g_signal_emit_by_name (context, "preedit-end"); -} - -static void -text_input_commit (void *data, - struct gtk_text_input *text_input, - const char *text) -{ - GtkIMContextWaylandGlobal *global = data; - - if (global->current && text) - g_signal_emit_by_name (global->current, "commit", text); -} - -static void -text_input_delete_surrounding_text (void *data, - struct gtk_text_input *text_input, - uint32_t offset, - uint32_t len) -{ - GtkIMContextWaylandGlobal *global = data; - - if (global->current) - g_signal_emit_by_name (global->current, "delete-surrounding", offset, len); -} - -static const struct gtk_text_input_listener text_input_listener = { - text_input_enter, - text_input_leave, - text_input_preedit, - text_input_commit, - text_input_delete_surrounding_text -}; - -static void -registry_handle_global (void *data, - struct wl_registry *registry, - uint32_t id, - const char *interface, - uint32_t version) -{ - GtkIMContextWaylandGlobal *global = data; - GdkSeat *seat = gdk_display_get_default_seat (gdk_display_get_default ()); - - if (strcmp (interface, "gtk_text_input_manager") == 0) - { - global->text_input_manager = - wl_registry_bind (global->registry, id, - >k_text_input_manager_interface, 1); - global->text_input = - gtk_text_input_manager_get_text_input (global->text_input_manager, - gdk_wayland_seat_get_wl_seat (seat)); - gtk_text_input_add_listener (global->text_input, - &text_input_listener, global); - } -} - -static void -registry_handle_global_remove (void *data, - struct wl_registry *registry, - uint32_t id) -{ - GtkIMContextWaylandGlobal *global = data; - - gtk_text_input_destroy (global->text_input); - global->text_input = NULL; - - gtk_text_input_manager_destroy (global->text_input_manager); - global->text_input_manager = NULL; -} - -static const struct wl_registry_listener registry_listener = { - registry_handle_global, - registry_handle_global_remove -}; - -static void -gtk_im_context_wayland_global_init (GdkDisplay *display) -{ - if (global) - return; - - global = g_new0 (GtkIMContextWaylandGlobal, 1); - global->display = gdk_wayland_display_get_wl_display (display); - global->registry = wl_display_get_registry (global->display); - - wl_registry_add_listener (global->registry, ®istry_listener, global); -} - -static void -notify_surrounding_text (GtkIMContextWayland *context) -{ - if (!global || !global->text_input) - return; - if (global->current != GTK_IM_CONTEXT (context)) - return; - if (!context->surrounding.text) - return; - - gtk_text_input_set_surrounding_text (global->text_input, - context->surrounding.text, - context->surrounding.cursor_idx, - context->surrounding.cursor_idx); -} - -static void -notify_cursor_location (GtkIMContextWayland *context) -{ - cairo_rectangle_int_t rect; - - if (!global || !global->text_input) - return; - if (global->current != GTK_IM_CONTEXT (context)) - return; - if (!context->widget) - return; - - rect = context->cursor_rect; - gtk_widget_translate_coordinates (context->widget, - gtk_widget_get_toplevel (context->widget), - rect.x, rect.y, - &rect.x, &rect.y); - - gtk_text_input_set_cursor_rectangle (global->text_input, - rect.x, rect.y, - rect.width, rect.height); -} - -static uint32_t -translate_hints (GtkInputHints input_hints, - GtkInputPurpose purpose) -{ - uint32_t hints = 0; - - if (input_hints & GTK_INPUT_HINT_SPELLCHECK) - hints |= GTK_TEXT_INPUT_CONTENT_HINT_SPELLCHECK; - if (input_hints & GTK_INPUT_HINT_WORD_COMPLETION) - hints |= GTK_TEXT_INPUT_CONTENT_HINT_COMPLETION; - if (input_hints & GTK_INPUT_HINT_LOWERCASE) - hints |= GTK_TEXT_INPUT_CONTENT_HINT_LOWERCASE; - if (input_hints & GTK_INPUT_HINT_UPPERCASE_CHARS) - hints |= GTK_TEXT_INPUT_CONTENT_HINT_UPPERCASE; - if (input_hints & GTK_INPUT_HINT_UPPERCASE_WORDS) - hints |= GTK_TEXT_INPUT_CONTENT_HINT_TITLECASE; - if (input_hints & GTK_INPUT_HINT_UPPERCASE_SENTENCES) - hints |= GTK_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION; - - if (purpose == GTK_INPUT_PURPOSE_PIN || - purpose == GTK_INPUT_PURPOSE_PASSWORD) - { - hints |= (GTK_TEXT_INPUT_CONTENT_HINT_HIDDEN_TEXT | - GTK_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA); - } - - return hints; -} - -static uint32_t -translate_purpose (GtkInputPurpose purpose) -{ - switch (purpose) - { - case GTK_INPUT_PURPOSE_FREE_FORM: - return GTK_TEXT_INPUT_CONTENT_PURPOSE_NORMAL; - case GTK_INPUT_PURPOSE_ALPHA: - return GTK_TEXT_INPUT_CONTENT_PURPOSE_ALPHA; - case GTK_INPUT_PURPOSE_DIGITS: - return GTK_TEXT_INPUT_CONTENT_PURPOSE_DIGITS; - case GTK_INPUT_PURPOSE_NUMBER: - return GTK_TEXT_INPUT_CONTENT_PURPOSE_NUMBER; - case GTK_INPUT_PURPOSE_PHONE: - return GTK_TEXT_INPUT_CONTENT_PURPOSE_PHONE; - case GTK_INPUT_PURPOSE_URL: - return GTK_TEXT_INPUT_CONTENT_PURPOSE_URL; - case GTK_INPUT_PURPOSE_EMAIL: - return GTK_TEXT_INPUT_CONTENT_PURPOSE_EMAIL; - case GTK_INPUT_PURPOSE_NAME: - return GTK_TEXT_INPUT_CONTENT_PURPOSE_NAME; - case GTK_INPUT_PURPOSE_PASSWORD: - return GTK_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD; - case GTK_INPUT_PURPOSE_PIN: - return GTK_TEXT_INPUT_CONTENT_PURPOSE_PIN; - } - - return GTK_TEXT_INPUT_CONTENT_PURPOSE_NORMAL; -} - -static void -notify_content_type (GtkIMContextWayland *context) -{ - GtkInputHints hints; - GtkInputPurpose purpose; - - if (global->current != GTK_IM_CONTEXT (context)) - return; - - g_object_get (context, - "input-hints", &hints, - "input-purpose", &purpose, - NULL); - - gtk_text_input_set_content_type (global->text_input, - translate_hints (hints, purpose), - translate_purpose (purpose)); -} - -static void -commit_state (GtkIMContextWayland *context) -{ - if (global->current != GTK_IM_CONTEXT (context)) - return; - gtk_text_input_commit (global->text_input); -} - -static void -enable_text_input (GtkIMContextWayland *context, - gboolean toggle_panel) -{ - guint flags = 0; - - if (context->use_preedit) - flags |= GTK_TEXT_INPUT_ENABLE_FLAGS_CAN_SHOW_PREEDIT; - if (toggle_panel) - flags |= GTK_TEXT_INPUT_ENABLE_FLAGS_TOGGLE_INPUT_PANEL; - - gtk_text_input_enable (global->text_input, - global->enter_serial, - flags); -} - -static void -gtk_im_context_wayland_finalize (GObject *object) -{ - GtkIMContextWayland *context = GTK_IM_CONTEXT_WAYLAND (object); - - g_clear_object (&context->widget); - g_clear_object (&context->gesture); - - G_OBJECT_CLASS (gtk_im_context_wayland_parent_class)->finalize (object); -} - -static void -pressed_cb (GtkGestureMultiPress *gesture, - gint n_press, - gdouble x, - gdouble y, - GtkIMContextWayland *context) -{ - if (n_press == 1) - { - context->press_x = x; - context->press_y = y; - } -} - -static void -released_cb (GtkGestureMultiPress *gesture, - gint n_press, - gdouble x, - gdouble y, - GtkIMContextWayland *context) -{ - GtkInputHints hints; - - g_object_get (context, "input-hints", &hints, NULL); - - if (n_press == 1 && - (hints & GTK_INPUT_HINT_INHIBIT_OSK) == 0 && - !gtk_drag_check_threshold (context->widget, - context->press_x, - context->press_y, - x, y)) - { - enable_text_input (GTK_IM_CONTEXT_WAYLAND (context), TRUE); - } -} - -static void -gtk_im_context_wayland_set_client_widget (GtkIMContext *context, - GtkWidget *widget) -{ - GtkIMContextWayland *context_wayland = GTK_IM_CONTEXT_WAYLAND (context); - - if (widget == context_wayland->widget) - return; - - if (context_wayland->widget && context_wayland->widget != widget) - g_clear_object (&context_wayland->gesture); - - g_set_object (&context_wayland->widget, widget); - - if (widget) - { - GtkGesture *gesture; - - gesture = gtk_gesture_multi_press_new (widget); - gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (gesture), - GTK_PHASE_CAPTURE); - g_signal_connect (gesture, "pressed", - G_CALLBACK (pressed_cb), context); - g_signal_connect (gesture, "released", - G_CALLBACK (released_cb), context); - context_wayland->gesture = gesture; - } -} - -static void -gtk_im_context_wayland_get_preedit_string (GtkIMContext *context, - gchar **str, - PangoAttrList **attrs, - gint *cursor_pos) -{ - GtkIMContextWayland *context_wayland = GTK_IM_CONTEXT_WAYLAND (context); - gchar *preedit_str; - - 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) - return; - - preedit_str = - context_wayland->preedit.text ? context_wayland->preedit.text : ""; - - if (str) - *str = g_strdup (preedit_str); - if (cursor_pos) - *cursor_pos = context_wayland->preedit.cursor_idx; - - if (attrs) - { - *attrs = pango_attr_list_new (); - pango_attr_list_insert (*attrs, - pango_attr_underline_new (PANGO_UNDERLINE_SINGLE)); - } -} - -static gboolean -gtk_im_context_wayland_filter_keypress (GtkIMContext *context, - GdkEventKey *key) -{ - /* This is done by the compositor */ - return GTK_IM_CONTEXT_CLASS (gtk_im_context_wayland_parent_class)->filter_keypress (context, key); -} - -static void -gtk_im_context_wayland_focus_in (GtkIMContext *context) -{ - GtkIMContextWayland *context_wayland = GTK_IM_CONTEXT_WAYLAND (context); - - if (global->current == context) - return; - if (!global->text_input) - return; - - global->current = context; - enable_text_input (context_wayland, FALSE); - notify_content_type (context_wayland); - notify_surrounding_text (context_wayland); - notify_cursor_location (context_wayland); - commit_state (context_wayland); -} - -static void -gtk_im_context_wayland_focus_out (GtkIMContext *context) -{ - if (global->current != context) - return; - - gtk_text_input_disable (global->text_input); - global->current = NULL; -} - -static void -gtk_im_context_wayland_reset (GtkIMContext *context) -{ - reset_preedit (GTK_IM_CONTEXT_WAYLAND (context)); - - GTK_IM_CONTEXT_CLASS (gtk_im_context_wayland_parent_class)->reset (context); -} - -static void -gtk_im_context_wayland_set_cursor_location (GtkIMContext *context, - GdkRectangle *rect) -{ - GtkIMContextWayland *context_wayland; - - context_wayland = GTK_IM_CONTEXT_WAYLAND (context); - - context_wayland->cursor_rect = *rect; - notify_cursor_location (context_wayland); - commit_state (context_wayland); -} - -static void -gtk_im_context_wayland_set_use_preedit (GtkIMContext *context, - gboolean use_preedit) -{ - GtkIMContextWayland *context_wayland = GTK_IM_CONTEXT_WAYLAND (context); - - context_wayland->use_preedit = !!use_preedit; -} - -static void -gtk_im_context_wayland_set_surrounding (GtkIMContext *context, - const gchar *text, - gint len, - gint cursor_index) -{ - GtkIMContextWayland *context_wayland; - - context_wayland = GTK_IM_CONTEXT_WAYLAND (context); - - g_free (context_wayland->surrounding.text); - context_wayland->surrounding.text = g_strdup (text); - context_wayland->surrounding.cursor_idx = cursor_index; - - notify_surrounding_text (context_wayland); - commit_state (context_wayland); -} - -static gboolean -gtk_im_context_wayland_get_surrounding (GtkIMContext *context, - gchar **text, - gint *cursor_index) -{ - GtkIMContextWayland *context_wayland; - - context_wayland = GTK_IM_CONTEXT_WAYLAND (context); - - if (!context_wayland->surrounding.text) - return FALSE; - - *text = context_wayland->surrounding.text; - *cursor_index = context_wayland->surrounding.cursor_idx; - return TRUE; -} - -static void -gtk_im_context_wayland_class_init (GtkIMContextWaylandClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkIMContextClass *im_context_class = GTK_IM_CONTEXT_CLASS (klass); - - object_class->finalize = gtk_im_context_wayland_finalize; - - im_context_class->set_client_widget = gtk_im_context_wayland_set_client_widget; - im_context_class->get_preedit_string = gtk_im_context_wayland_get_preedit_string; - im_context_class->filter_keypress = gtk_im_context_wayland_filter_keypress; - im_context_class->focus_in = gtk_im_context_wayland_focus_in; - im_context_class->focus_out = gtk_im_context_wayland_focus_out; - im_context_class->reset = gtk_im_context_wayland_reset; - im_context_class->set_cursor_location = gtk_im_context_wayland_set_cursor_location; - 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; -} - -static void -gtk_im_context_wayland_class_finalize (GtkIMContextWaylandClass *class) -{ -} - -static void -on_content_type_changed (GtkIMContextWayland *context) -{ - notify_content_type (context); - commit_state (context); -} - -static void -gtk_im_context_wayland_init (GtkIMContextWayland *context) -{ - context->use_preedit = TRUE; - g_signal_connect_swapped (context, "notify::input-purpose", - G_CALLBACK (on_content_type_changed), context); - g_signal_connect_swapped (context, "notify::input-hints", - G_CALLBACK (on_content_type_changed), context); -} diff --git a/modules/input/meson.build b/modules/input/meson.build deleted file mode 100644 index ae904b8e8d..0000000000 --- a/modules/input/meson.build +++ /dev/null @@ -1,118 +0,0 @@ -# Note: this file is included from the top-level before gtk/meson.build. -# The actual input modules are then built in gtk/meson.build based on the -# defs we provide here. It has to be that way because included input methods -# need to be built before libgtk-4.so is built, so before gtk/meson.build, but -# all input methods also rely on gtk generated headers to be created first, so -# there is a bit of an ordering problem which we solve by collecting all the -# information here but moving the actual build definitions to gtk/meson.build. -build_dynamic_modules = false -dynamic_modules = get_option('dynamic-modules') -if dynamic_modules - gmodule_supported = dependency('gmodule-no-export-2.0').get_pkgconfig_variable('gmodule_supported') - if gmodule_supported == 'true' - build_dynamic_modules = true - else - message('Modules are not supported according to gmodule-no-export-2.0.pc') - endif -endif - -all_immodules = backend_immodules - -# Allow building some or all immodules included -included_immodules = get_option('included-immodules').split(',') -if included_immodules.contains('none') - included_immodules = [] -elif included_immodules.contains('all') - included_immodules = all_immodules -endif - -have_included_immodules = included_immodules.length() > 0 - -foreach im: included_immodules - if not all_immodules.contains(im) - error('The specified input method "@0@" is not available (available methods: @1@)'.format(im, ', '.join(all_immodules))) - endif -endforeach - -immodules_subdir = 'gtk-4.0/@0@/immodules'.format(gtk_binary_version) -immodules_install_dir = join_paths(gtk_libdir, immodules_subdir) - -# Format: -# - protocol name -# - protocol stability ('stable' or 'unstable') -# - protocol version (if stability is 'unstable') -proto_sources = [ - ['gtk-text-input', 'stable', ], -] - -im_wayland_gen_headers = [] -im_wayland_sources = files('imwayland.c') -wayland_scanner = find_program('wayland-scanner') -genprotocols = find_program('../../gdk/wayland/genprotocolfiles.py') - -foreach p: proto_sources - proto_name = p.get(0) - proto_stability = p.get(1) - - if proto_stability == 'stable' - output_base = proto_name - input = '@0@.xml'.format(proto_name) - else - proto_version = p.get(2) - output_base = '@0@-@1@-@2@'.format(proto_name, proto_stability, proto_version) - input = join_paths(proto_dir, '@0@/@1@/@2@.xml'.format(proto_stability, proto_name, output_base)) - endif - - im_wayland_sources += custom_target('@0@ client header'.format(output_base), - input: input, - output: '@0@-client-protocol.h'.format(output_base), - command: [ - genprotocols, - wayland_scanner, - '@INPUT@', '@OUTPUT@', - 'client-header', - ]) - - im_wayland_sources += custom_target('@0@ source'.format(output_base), - input: input, - output: '@0@-protocol.c'.format(output_base), - command: [ - genprotocols, - wayland_scanner, - '@INPUT@', '@OUTPUT@', - 'code', - ]) -endforeach - -method_defs = [ - ['broadway', files('imbroadway.c')], - ['quartz', ('imquartz.c'), [], ('-xobjective-c')], - ['xim', files('gtkimcontextxim.c')], - ['ime', files('gtkimcontextime.c'), ['imm32']], - ['wayland', im_wayland_sources], -] - -inc_im_method_defs = [] -dyn_im_method_defs = [] - -foreach m: method_defs - im = m.get(0) - srcs = m.get(1) - cargs = m.get(3, []) - libs = [] - - # only use backend-specific input methods for backends that are enabled - if all_immodules.contains(im) - # check for extra libs lazily - foreach libname: m.get(2, []) - libs += [cc.find_library(libname)] - endforeach - - if included_immodules.contains(im) - cdata.set('INCLUDE_IM_@0@'.format(im.underscorify()), true) - inc_im_method_defs += [[im, srcs, cargs, libs]] - elif build_dynamic_modules - dyn_im_method_defs += [[im, srcs, cargs, libs]] - endif - endif -endforeach diff --git a/modules/meson.build b/modules/meson.build index d0c4adc81d..cde966a094 100644 --- a/modules/meson.build +++ b/modules/meson.build @@ -1,5 +1,3 @@ -# Note: 'input' subdir has already been included from top-level. - if os_unix subdir('printbackends') endif |