2
* Copyright (C) 2010, Intel Corporation.
3
* Copyright (C) 2012 One Laptop per Child Association
5
* Author: Raymond Liu <raymond.liu@intel.com>
8
* This library is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Lesser General Public License
10
* version 2.1 as published by the Free Software Foundation.
12
* This library is distributed in the hope that it will be useful, but
13
* WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this library; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24
#include <X11/keysym.h>
25
#include <gdk/gdkx.h> // For retrieving XID
26
#include <maliit-glib/maliitattributeextensionprivate.h>
28
#include "client-imcontext-gtk.h"
29
#include "qt-gtk-translate.h"
32
static GType _meego_imcontext_type = 0;
33
static GtkIMContextClass *parent_class = NULL;
35
static MeegoIMContext *focused_imcontext = NULL;
36
static GtkWidget *focused_widget = NULL;
38
gboolean redirect_keys = FALSE;
40
static void meego_imcontext_finalize(GObject *object);
42
static void meego_imcontext_class_init(MeegoIMContextClass *klass);
43
static void meego_imcontext_init(MeegoIMContext *meego_imcontext);
45
static void meego_imcontext_focus_in(GtkIMContext *context);
46
static void meego_imcontext_focus_out(GtkIMContext *context);
47
static gboolean meego_imcontext_filter_key_event(GtkIMContext *context, GdkEventKey *event);
48
static void meego_imcontext_reset(GtkIMContext *context);
49
static void meego_imcontext_get_preedit_string(GtkIMContext *context, gchar **str, PangoAttrList **attrs, gint *cursor_pos);
50
static void meego_imcontext_set_preedit_enabled(GtkIMContext *context, gboolean enabled);
51
static void meego_imcontext_set_client_window(GtkIMContext *context, GdkWindow *window);
52
static void meego_imcontext_set_cursor_location(GtkIMContext *context, GdkRectangle *area);
53
static void meego_imcontext_update_widget_info(MeegoIMContext *imcontext);
55
static void meego_imcontext_im_initiated_hide(MeegoIMContextDbusObj *obj, gpointer user_data);
56
static void meego_imcontext_commit_string(MeegoIMContextDbusObj *obj, char *string, int replacement_start,
57
int replacement_length, int cursor_pos, gpointer user_data);
58
static void meego_imcontext_update_preedit(MeegoIMContextDbusObj *obj, const char *string, GPtrArray *formatListData, gint32 replaceStart, gint32 replaceLength, gint32 cursorPos, gpointer user_data);
59
static void meego_imcontext_key_event(MeegoIMContextDbusObj *obj, int type, int key, int modifiers, char *text,
60
gboolean auto_repeat, int count, gpointer user_data);
61
static void meego_imcontext_copy(MeegoIMContextDbusObj *obj, gpointer user_data);
62
static void meego_imcontext_paste(MeegoIMContextDbusObj *obj, gpointer user_data);
63
static void meego_imcontext_invoke_action(MeegoIMContextDbusObj *obj, const char *action, const char* sequence, gpointer user_data);
64
static void meego_imcontext_set_redirect_keys(MeegoIMContextDbusObj *obj, gboolean enabled, gpointer user_data);
65
static void meego_imcontext_notify_extended_attribute_changed (MeegoIMContextDbusObj *obj, gint id, const gchar *target, const gchar *target_item, const gchar *attribute, GVariant *variant_value, gpointer user_data);
66
static void meego_imcontext_update_input_method_area (MeegoIMContextDbusObj *obj, int x, int y, int width, int height, gpointer user_data);
69
static GtkIMContext *meego_imcontext_get_slave_imcontext(void);
71
static const gchar *const WIDGET_INFO_WIN_ID = "winId";
72
static const gchar *const WIDGET_INFO_FOCUS_STATE = "focusState";
73
static const gchar *const WIDGET_INFO_ATTRIBUTE_EXTENSION_ID = "toolbarId";
74
static const gchar *const WIDGET_INFO_ATTRIBUTE_EXTENSION_FILENAME = "toolbar";
75
static const gchar *const WIDGET_INFO_SURROUNDING_TEXT = "surroundingText";
76
static const gchar *const WIDGET_INFO_CURSOR_POSITION = "cursorPosition";
78
void destroy_g_value(GValue *value)
84
GType meego_imcontext_get_type()
86
return _meego_imcontext_type;
91
meego_imcontext_register_type(GTypeModule *type_module)
93
static const GTypeInfo meego_imcontext_info = {
94
sizeof(MeegoIMContextClass),
96
(GBaseFinalizeFunc) NULL,
97
(GClassInitFunc) meego_imcontext_class_init,
100
sizeof(MeegoIMContext),
102
(GInstanceInitFunc) meego_imcontext_init,
106
if (_meego_imcontext_type)
110
_meego_imcontext_type =
111
g_type_module_register_type(
115
&meego_imcontext_info,
118
_meego_imcontext_type =
119
g_type_register_static(
122
&meego_imcontext_info,
129
// staff for fallback slave GTK simple imcontext
131
slave_commit(GtkIMContext *slave, const char *text, gpointer data)
135
DBG("text = %s", text);
136
if (focused_imcontext && text) {
137
g_signal_emit_by_name(focused_imcontext, "commit", text);
143
slave_preedit_changed(GtkIMContext *slave, gpointer data)
148
PangoAttrList *attrs = NULL;
151
if (!focused_imcontext || !slave)
154
gtk_im_context_get_preedit_string(slave, &str, &attrs, &cursor_pos);
157
g_free(focused_imcontext->preedit_str);
158
focused_imcontext->preedit_str = str;
161
focused_imcontext->preedit_cursor_pos = cursor_pos;
163
if (focused_imcontext->preedit_attrs != NULL)
164
pango_attr_list_unref(focused_imcontext->preedit_attrs);
166
focused_imcontext->preedit_attrs = attrs;
168
g_signal_emit_by_name(focused_imcontext, "preedit-changed");
172
static GtkIMContext *
173
meego_imcontext_get_slave_imcontext(void)
175
static GtkIMContext *slave_ic = NULL;
178
slave_ic = gtk_im_context_simple_new();
179
//g_signal_connect(G_OBJECT(slave_ic), "preedit-start", G_CALLBACK(slave_preedit_start), NULL);
180
//g_signal_connect(G_OBJECT(slave_ic), "preedit-end", G_CALLBACK(slave_preedit_end), NULL);
181
g_signal_connect(G_OBJECT(slave_ic), "preedit-changed", G_CALLBACK(slave_preedit_changed), NULL);
182
g_signal_connect(G_OBJECT(slave_ic), "commit", G_CALLBACK(slave_commit), NULL);
190
meego_imcontext_new(void)
192
MeegoIMContext *ic = MEEGO_IMCONTEXT(g_object_new(MEEGO_TYPE_IMCONTEXT, NULL));
193
return GTK_IM_CONTEXT(ic);
198
meego_imcontext_finalize(GObject *object)
200
MeegoIMContext *imcontext = MEEGO_IMCONTEXT(object);
202
g_hash_table_destroy(imcontext->widget_state);
204
if (imcontext->client_window)
205
g_object_unref(imcontext->client_window);
207
if (imcontext->registry)
208
g_object_unref(imcontext->registry);
210
g_signal_handlers_disconnect_by_data (imcontext->connector->dbusobj, object);
211
g_signal_handlers_disconnect_by_data (imcontext->proxy, object);
213
G_OBJECT_CLASS(parent_class)->finalize(object);
218
meego_imcontext_class_init(MeegoIMContextClass *klass)
220
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
221
parent_class = (GtkIMContextClass *)g_type_class_peek_parent(klass);
222
GtkIMContextClass *imclass = GTK_IM_CONTEXT_CLASS(klass);
224
gobject_class->finalize = meego_imcontext_finalize;
226
imclass->focus_in = meego_imcontext_focus_in;
227
imclass->focus_out = meego_imcontext_focus_out;
228
imclass->filter_keypress = meego_imcontext_filter_key_event;
229
imclass->reset = meego_imcontext_reset;
230
imclass->set_client_window = meego_imcontext_set_client_window;
231
imclass->get_preedit_string = meego_imcontext_get_preedit_string;
232
imclass->set_cursor_location = meego_imcontext_set_cursor_location;
233
imclass->set_use_preedit = meego_imcontext_set_preedit_enabled;
238
meego_imcontext_init(MeegoIMContext *self)
240
self->client_window = NULL;
242
self->cursor_location.x = -1;
243
self->cursor_location.y = -1;
244
self->cursor_location.width = 0;
245
self->cursor_location.height = 0;
247
self->preedit_str = NULL;
248
self->preedit_attrs = NULL;
249
self->preedit_cursor_pos = 0;
251
self->widget_state = g_hash_table_new_full(&g_str_hash, &g_str_equal,
252
&g_free, (GDestroyNotify)destroy_g_value);
253
self->focus_state = FALSE;
255
self->connector = meego_im_connector_get_singleton();
256
self->proxy = self->connector->proxy;
258
self->registry = maliit_attribute_extension_registry_get_instance();
260
MeegoIMContextDbusObj *dbusobj = self->connector->dbusobj;
261
g_signal_connect(dbusobj, "im-initiated-hide",
262
G_CALLBACK(meego_imcontext_im_initiated_hide), self);
263
g_signal_connect(dbusobj, "commit-string",
264
G_CALLBACK(meego_imcontext_commit_string), self);
265
g_signal_connect(dbusobj, "update-preedit",
266
G_CALLBACK(meego_imcontext_update_preedit), self);
267
g_signal_connect(dbusobj, "key-event",
268
G_CALLBACK(meego_imcontext_key_event), self);
269
g_signal_connect(dbusobj, "copy",
270
G_CALLBACK(meego_imcontext_copy), self);
271
g_signal_connect(dbusobj, "paste",
272
G_CALLBACK(meego_imcontext_paste), self);
273
g_signal_connect(dbusobj, "set-redirect-keys",
274
G_CALLBACK(meego_imcontext_set_redirect_keys), self);
275
g_signal_connect(dbusobj, "notify-extended-attribute-changed",
276
G_CALLBACK(meego_imcontext_notify_extended_attribute_changed), self);
277
g_signal_connect(dbusobj, "update-input-method-area",
278
G_CALLBACK(meego_imcontext_update_input_method_area), self);
279
g_signal_connect(self->proxy, "invoke-action",
280
G_CALLBACK(meego_imcontext_invoke_action), self);
285
meego_imcontext_focus_in(GtkIMContext *context)
287
MeegoIMContext *imcontext = MEEGO_IMCONTEXT(context);
289
gboolean focus_changed = TRUE;
291
DBG("imcontext = %p", imcontext);
293
if (focused_imcontext && focused_imcontext != imcontext)
294
meego_imcontext_focus_out(GTK_IM_CONTEXT(focused_imcontext));
295
focused_imcontext = imcontext;
297
imcontext->focus_state = TRUE;
298
meego_imcontext_update_widget_info(imcontext);
300
ret = meego_im_proxy_activate_context(imcontext->proxy);
302
meego_im_proxy_update_widget_info(imcontext->proxy,
303
imcontext->widget_state, focus_changed);
304
meego_im_proxy_show_input_method(imcontext->proxy);
306
// TODO: anything else than call "activateContext" and "showInputMethod" ?
312
meego_imcontext_focus_out(GtkIMContext *context)
314
MeegoIMContext *imcontext = MEEGO_IMCONTEXT(context);
315
DBG("imcontext = %p", imcontext);
317
meego_imcontext_reset(context);
319
imcontext->focus_state = FALSE;
320
focused_imcontext = NULL;
321
focused_widget = NULL;
323
meego_imcontext_update_widget_info(imcontext);
324
meego_im_proxy_update_widget_info(imcontext->proxy,
325
imcontext->widget_state, TRUE);
327
meego_im_proxy_hide_input_method(imcontext->proxy);
329
// TODO: anything else than call "hideInputMethod" ?
334
meego_imcontext_filter_key_event(GtkIMContext *context, GdkEventKey *event)
336
MeegoIMContext *imcontext = MEEGO_IMCONTEXT(context);
337
int qevent_type = 0, qt_keycode = 0, qt_modifier = 0;
340
focused_widget = gtk_get_event_widget((GdkEvent *)event);
342
DBG("event type=0x%x, state=0x%x, keyval=0x%x, keycode=0x%x, group=%d",
343
event->type, event->state, event->keyval, event->hardware_keycode, event->group);
345
if (focused_imcontext != imcontext)
346
meego_imcontext_focus_in(context);
348
if ((event->state & IM_FORWARD_MASK) || !redirect_keys) {
349
GtkIMContext *slave = meego_imcontext_get_slave_imcontext();
350
return gtk_im_context_filter_keypress(slave, event);
353
if (!gdk_key_event_to_qt(event, &qevent_type, &qt_keycode, &qt_modifier))
356
meego_im_proxy_process_key_event(imcontext->proxy, qevent_type, qt_keycode, qt_modifier,
357
text, 0, 1, event->hardware_keycode, event->state, event->time);
364
meego_imcontext_reset(GtkIMContext *context)
366
MeegoIMContext *imcontext = MEEGO_IMCONTEXT(context);
367
DBG("imcontext = %p", imcontext);
369
if (imcontext != focused_imcontext) {
373
/* Commit preedit if it is not empty */
374
if (focused_imcontext && focused_imcontext->preedit_str && focused_imcontext->preedit_str[0]) {
375
char *commit_string = focused_imcontext->preedit_str;
376
focused_imcontext->preedit_str = g_strdup("");
377
focused_imcontext->preedit_cursor_pos = 0;
378
g_signal_emit_by_name(focused_imcontext, "preedit-changed");
379
g_signal_emit_by_name(focused_imcontext, "commit", commit_string);
380
g_free(commit_string);
383
meego_im_proxy_reset(imcontext->proxy);
388
meego_imcontext_get_preedit_string(GtkIMContext *context, gchar **str, PangoAttrList **attrs, gint *cursor_pos)
390
MeegoIMContext *imcontext = MEEGO_IMCONTEXT(context);
392
DBG("imcontext = %p", imcontext);
395
if (imcontext->preedit_str)
396
*str = g_strdup(imcontext->preedit_str);
402
if (imcontext->preedit_attrs) {
403
*attrs = imcontext->preedit_attrs;
404
pango_attr_list_ref(imcontext->preedit_attrs);
406
*attrs = pango_attr_list_new();
411
*cursor_pos = imcontext->preedit_cursor_pos;
416
meego_imcontext_set_preedit_enabled(GtkIMContext *context, gboolean enabled)
420
// TODO: Seems QT/MEEGO don't need it, it will always showing preedit.
426
meego_imcontext_set_client_window(GtkIMContext *context, GdkWindow *window)
428
MeegoIMContext *imcontext = MEEGO_IMCONTEXT(context);
431
if (imcontext->client_window)
432
g_object_unref(imcontext->client_window);
435
g_object_ref(window);
437
imcontext->client_window = window;
439
// TODO: might need to update cursor position or other staff later using this info?
444
meego_imcontext_set_cursor_location(GtkIMContext *context, GdkRectangle *area)
446
MeegoIMContext *imcontext = MEEGO_IMCONTEXT(context);
447
//DBG("imcontext = %p, x=%d, y=%d, w=%d, h=%d", imcontext,
448
// area->x, area->y, area->width, area->height);
450
imcontext->cursor_location = *area;
452
// TODO: call updateWidgetInformation?
453
//The cursor location from GTK widget is simillar to ImMicroFocus info of a QWidget
454
//Thus we might need to update Qt::ImMicroFocus info according to this.
455
//But MEEGO IM seems not using this info at all
458
/* Update the widget_state map with current information about the widget. */
460
meego_imcontext_update_widget_info(MeegoIMContext *imcontext)
463
g_hash_table_remove_all(imcontext->widget_state);
466
GValue *focus_value = g_new0(GValue, 1);
467
g_value_init(focus_value, G_TYPE_BOOLEAN);
468
g_value_set_boolean(focus_value, imcontext->focus_state);
469
g_hash_table_insert(imcontext->widget_state, g_strdup(WIDGET_INFO_FOCUS_STATE), focus_value);
471
if (!imcontext->focus_state)
475
if (imcontext->client_window) {
476
guint64 xid = GDK_WINDOW_XID(imcontext->client_window);
477
GValue *xid_value = g_new0(GValue, 1);
478
g_value_init(xid_value, G_TYPE_UINT64);
479
g_value_set_uint64(xid_value, xid);
480
g_hash_table_insert(imcontext->widget_state, g_strdup(WIDGET_INFO_WIN_ID), xid_value);
483
/* Attribute extensions */
484
if (imcontext->client_window) {
485
gpointer user_data = NULL;
486
GtkWidget* widget = NULL;
487
MaliitAttributeExtension *extension;
489
GValue *filename_value;
491
gdk_window_get_user_data (imcontext->client_window, &user_data);
493
widget = GTK_WIDGET (user_data);
495
user_data = g_object_get_qdata (G_OBJECT (widget),
496
MALIIT_ATTRIBUTE_EXTENSION_DATA_QUARK);
499
extension = MALIIT_ATTRIBUTE_EXTENSION (user_data);
500
id_value = g_new0 (GValue, 1);
501
filename_value = g_new0 (GValue, 1);
503
g_value_init (id_value, G_TYPE_INT);
504
g_value_set_int (id_value, maliit_attribute_extension_get_id (extension));
505
g_value_init (filename_value, G_TYPE_STRING);
506
g_value_set_string (filename_value, maliit_attribute_extension_get_filename (extension));
507
g_hash_table_replace (imcontext->widget_state,
508
g_strdup(WIDGET_INFO_ATTRIBUTE_EXTENSION_ID),
510
g_hash_table_replace (imcontext->widget_state,
511
g_strdup(WIDGET_INFO_ATTRIBUTE_EXTENSION_FILENAME),
516
/* Surrounding text */
517
GtkIMContext *context = GTK_IM_CONTEXT(imcontext);
518
gchar *surrounding_text;
520
if (gtk_im_context_get_surrounding(context, &surrounding_text, &cursor_index))
522
GValue *surrounding_text_value = g_new0 (GValue, 1);
523
GValue *cursor_position_value = g_new0 (GValue, 1);
525
g_value_init (surrounding_text_value, G_TYPE_STRING);
526
g_value_take_string (surrounding_text_value, surrounding_text);
527
g_hash_table_replace(imcontext->widget_state, g_strdup(WIDGET_INFO_SURROUNDING_TEXT), surrounding_text_value);
529
g_value_init (cursor_position_value, G_TYPE_INT);
530
g_value_set_int(cursor_position_value, cursor_index);
531
g_hash_table_replace(imcontext->widget_state, g_strdup(WIDGET_INFO_CURSOR_POSITION), cursor_position_value);
535
// Call back functions for dbus obj
537
meego_imcontext_im_initiated_hide(MeegoIMContextDbusObj *obj G_GNUC_UNUSED,
540
MeegoIMContext *imcontext = MEEGO_IMCONTEXT(user_data);
541
if (imcontext != focused_imcontext)
544
if (focused_imcontext && focused_imcontext->client_window) {
545
gpointer user_data = NULL;
546
GtkWidget* parent_widget = NULL;
548
gdk_window_get_user_data (focused_imcontext->client_window, &user_data);
550
parent_widget = GTK_WIDGET (user_data);
552
while (parent_widget && !GTK_IS_WINDOW (parent_widget)) {
553
parent_widget = gtk_widget_get_parent (parent_widget);
556
gtk_window_set_focus (GTK_WINDOW (parent_widget), NULL);
563
meego_imcontext_commit_string(MeegoIMContextDbusObj *obj G_GNUC_UNUSED,
565
int replacement_start G_GNUC_UNUSED,
566
int replacement_length G_GNUC_UNUSED,
567
int cursor_pos G_GNUC_UNUSED,
570
DBG("string is:%s", string);
572
MeegoIMContext *imcontext = MEEGO_IMCONTEXT(user_data);
573
if (imcontext != focused_imcontext)
576
if (focused_imcontext) {
577
g_free(focused_imcontext->preedit_str);
578
focused_imcontext->preedit_str = g_strdup("");
579
focused_imcontext->preedit_cursor_pos = 0;
580
g_signal_emit_by_name(focused_imcontext, "preedit-changed");
581
g_signal_emit_by_name(focused_imcontext, "commit", string);
587
MaliitPreeditDefault,
588
MaliitPreeditNoCandidates,
589
MaliitPreeditKeyPress,
590
MaliitPreeditUnconvertible,
595
get_byte_range_from_unicode_offsets (const gchar *string,
604
/* we provide start index and length in utf8 characters, but pango
605
* expects start and end indices in bytes.
607
if (g_utf8_validate (string, -1, NULL)) {
608
const gchar * const start_pointer = g_utf8_offset_to_pointer (string, utf8_start);
609
const gchar * const end_pointer = g_utf8_offset_to_pointer (string, utf8_start + utf8_length);
611
/* pointer arithmetics, there you have it. */
612
start = start_pointer - string;
613
end = end_pointer - string;
616
end = utf8_start + utf8_length;
628
meego_imcontext_update_preedit(MeegoIMContextDbusObj *obj G_GNUC_UNUSED,
630
GPtrArray *formatListData,
631
gint32 replaceStart G_GNUC_UNUSED,
632
gint32 replaceLength G_GNUC_UNUSED,
636
MeegoIMContext *imcontext = MEEGO_IMCONTEXT(user_data);
637
if (imcontext != focused_imcontext)
640
DBG("imcontext = %p string = %s cursorPos = %d", imcontext, string, cursorPos);
642
if (focused_imcontext) {
644
PangoAttrList* attrs;
646
g_free(focused_imcontext->preedit_str);
647
focused_imcontext->preedit_str = g_strdup(string);
648
/* If cursorPos is -1 explicitly set it to the end of the preedit */
649
if (cursorPos == -1) {
650
cursorPos = g_utf8_strlen(string, -1);
652
focused_imcontext->preedit_cursor_pos = cursorPos;
655
attrs = pango_attr_list_new();
657
for (iter = 0; iter < formatListData->len; ++iter) {
658
GValueArray *text_format = g_ptr_array_index (formatListData, iter);
659
gint start = g_value_get_int(g_value_array_get_nth(text_format, 0));
660
gint length = g_value_get_int(g_value_array_get_nth(text_format, 1));
661
MaliitPreeditFace preedit_face = (MaliitPreeditFace)g_value_get_int(g_value_array_get_nth(text_format, 2));
664
PangoAttribute* new_attrs[2] = { NULL, NULL };
667
get_byte_range_from_unicode_offsets(string, start, length, &byte_start, &byte_end);
669
switch (preedit_face) {
670
case MaliitPreeditNoCandidates:
671
new_attrs[0] = pango_attr_underline_new (PANGO_UNDERLINE_ERROR);
672
new_attrs[1] = pango_attr_underline_color_new (65535, 0, 0);
675
case MaliitPreeditUnconvertible: {
676
const gint gray = (2 << 15) - 1; /* halfway from 0 to 65535 */
678
new_attrs[0] = pango_attr_foreground_new (gray, gray, gray);
681
case MaliitPreeditActive:
682
new_attrs[0] = pango_attr_foreground_new(39168, 12800, 52224);
683
new_attrs[1] = pango_attr_weight_new(PANGO_WEIGHT_BOLD);
686
case MaliitPreeditKeyPress:
687
case MaliitPreeditDefault:
688
new_attrs[0] = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
689
new_attrs[1] = pango_attr_underline_color_new(0, 0, 0);
693
for (attr_iter = 0; attr_iter < 2; ++attr_iter) {
694
if (new_attrs[attr_iter]) {
695
new_attrs[attr_iter]->start_index = byte_start;
696
new_attrs[attr_iter]->end_index = byte_end;
698
pango_attr_list_insert(attrs, new_attrs[attr_iter]);
703
if (focused_imcontext->preedit_attrs) {
704
pango_attr_list_unref (focused_imcontext->preedit_attrs);
706
focused_imcontext->preedit_attrs = attrs;
708
g_signal_emit_by_name(focused_imcontext, "preedit-changed");
713
meego_imcontext_key_event(MeegoIMContextDbusObj *obj G_GNUC_UNUSED,
718
gboolean auto_repeat G_GNUC_UNUSED,
719
int count G_GNUC_UNUSED,
722
GdkEventKey *event = NULL;
723
GdkWindow *window = NULL;
726
MeegoIMContext *imcontext = MEEGO_IMCONTEXT(user_data);
727
if (imcontext != focused_imcontext)
730
if (focused_imcontext)
731
window = focused_imcontext->client_window;
733
event = qt_key_event_to_gdk(type, key, modifiers, text, window);
737
event->send_event = TRUE;
738
event->state |= IM_FORWARD_MASK;
740
gdk_event_put((GdkEvent *)event);
741
gdk_event_free((GdkEvent *)event);
745
meego_imcontext_copy(MeegoIMContextDbusObj *obj G_GNUC_UNUSED,
748
GdkWindow *window = NULL;
749
GdkEventKey *event = NULL;
753
MeegoIMContext *imcontext = MEEGO_IMCONTEXT(user_data);
754
if (imcontext != focused_imcontext)
757
if (focused_imcontext)
758
window = focused_imcontext->client_window;
760
event = compose_gdk_keyevent(GDK_KEY_PRESS, XK_C, GDK_CONTROL_MASK, window);
762
event->send_event = TRUE;
763
event->state |= IM_FORWARD_MASK;
764
gdk_event_put((GdkEvent *)event);
765
gdk_event_free((GdkEvent *)event);
768
event = compose_gdk_keyevent(GDK_KEY_RELEASE, XK_C, GDK_CONTROL_MASK, window);
770
event->send_event = TRUE;
771
event->state |= IM_FORWARD_MASK;
772
gdk_event_put((GdkEvent *)event);
773
gdk_event_free((GdkEvent *)event);
778
find_signal(const char *action, const char *alternative, GtkWidget *widget)
780
unsigned int signal = g_signal_lookup(action, G_OBJECT_TYPE(widget));
782
if (signal || alternative == NULL) {
786
return g_signal_lookup(alternative, G_OBJECT_TYPE(widget));
790
meego_imcontext_invoke_action(MeegoIMContextDbusObj *obj G_GNUC_UNUSED,
792
const char *sequence G_GNUC_UNUSED,
795
GtkWidget* widget = NULL;
796
MeegoIMContext *imcontext = MEEGO_IMCONTEXT(user_data);
798
if (imcontext != focused_imcontext)
801
gdk_window_get_user_data (imcontext->client_window, &user_data);
802
widget = GTK_WIDGET (user_data);
805
char *alternative = NULL;
808
if (g_strcmp0(action, "copy") == 0 ||
809
g_strcmp0(action, "cut") == 0 ||
810
g_strcmp0(action, "paste") == 0)
812
alternative = g_strdup_printf("%s-clipboard", action);
815
signal = find_signal(action, alternative, widget);
819
g_signal_emit(widget, signal, 0);
826
meego_imcontext_paste(MeegoIMContextDbusObj *obj G_GNUC_UNUSED,
829
GdkWindow *window = NULL;
830
GdkEventKey *event = NULL;
834
MeegoIMContext *imcontext = MEEGO_IMCONTEXT(user_data);
835
if (imcontext != focused_imcontext)
838
if (focused_imcontext)
839
window = focused_imcontext->client_window;
841
event = compose_gdk_keyevent(GDK_KEY_PRESS, XK_V, GDK_CONTROL_MASK, window);
843
event->send_event = TRUE;
844
event->state |= IM_FORWARD_MASK;
845
gdk_event_put((GdkEvent *)event);
846
gdk_event_free((GdkEvent *)event);
849
event = compose_gdk_keyevent(GDK_KEY_RELEASE, XK_V, GDK_CONTROL_MASK, window);
851
event->send_event = TRUE;
852
event->state |= IM_FORWARD_MASK;
853
gdk_event_put((GdkEvent *)event);
854
gdk_event_free((GdkEvent *)event);
859
meego_imcontext_set_redirect_keys(MeegoIMContextDbusObj *obj G_GNUC_UNUSED,
861
gpointer user_data G_GNUC_UNUSED)
863
DBG("enabled = %d", enabled);
864
redirect_keys = enabled;
868
meego_imcontext_notify_extended_attribute_changed (MeegoIMContextDbusObj *obj G_GNUC_UNUSED,
871
const gchar *target_item,
872
const gchar *attribute,
873
GVariant *variant_value,
874
gpointer user_data G_GNUC_UNUSED)
876
MeegoIMContext *imcontext = MEEGO_IMCONTEXT(user_data);
877
if (imcontext != focused_imcontext)
880
maliit_attribute_extension_registry_update_attribute (focused_imcontext->registry,
889
meego_imcontext_update_input_method_area (MeegoIMContextDbusObj *obj G_GNUC_UNUSED,
896
MeegoIMContext *imcontext = MEEGO_IMCONTEXT(user_data);
897
GdkRectangle cursor_rect, osk_rect = { x, y, width, height };
900
if (!imcontext->client_window)
903
if (imcontext->keyboard_area.x == x &&
904
imcontext->keyboard_area.y == y &&
905
imcontext->keyboard_area.width == width &&
906
imcontext->keyboard_area.height == height)
909
clear_area_id = g_signal_lookup ("clear-area", GTK_TYPE_IM_CONTEXT);
911
if (clear_area_id == 0)
914
imcontext->keyboard_area = osk_rect;
916
gdk_window_get_root_coords (imcontext->client_window,
917
imcontext->cursor_location.x,
918
imcontext->cursor_location.y,
919
&cursor_rect.x, &cursor_rect.y);
920
cursor_rect.width = imcontext->cursor_location.width;
921
cursor_rect.height = imcontext->cursor_location.height;
923
g_signal_emit (imcontext, clear_area_id, 0, &osk_rect, &cursor_rect);