示例#1
0
static void
fcitx_im_context_focus_out(GtkIMContext *context)
{
    FcitxLog(LOG_LEVEL, "fcitx_im_context_focus_out");
    FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context);

    if (!fcitxcontext->has_focus) {
        return;
    }

    g_assert (context == _focus_im_context);
    g_object_remove_weak_pointer ((GObject *) context,
                                  (gpointer *) &_focus_im_context);
    _focus_im_context = NULL;

    fcitxcontext->has_focus = false;

    if (fcitx_client_is_valid(fcitxcontext->client)) {
        fcitx_client_focus_out(fcitxcontext->client);
    }

    fcitxcontext->cursor_pos = 0;
    if (fcitxcontext->preedit_string != NULL) {
        g_free(fcitxcontext->preedit_string);
        fcitxcontext->preedit_string = NULL;
        g_signal_emit(fcitxcontext, _signal_preedit_changed_id, 0);
        g_signal_emit(fcitxcontext, _signal_preedit_end_id, 0);
    }

    gtk_im_context_focus_out(fcitxcontext->slave);

    return;
}
示例#2
0
static void
fcitx_im_context_finalize(GObject *obj)
{
    FcitxLog(LOG_LEVEL, "fcitx_im_context_finalize");
    FcitxIMContext *context = FCITX_IM_CONTEXT(obj);

    fcitx_im_context_set_client_window(GTK_IM_CONTEXT(context), NULL);

    g_object_unref(context->client);
    context->client = NULL;

    if (context->slave) {
        g_object_unref(context->slave);
        context->slave = NULL;
    }

    if (context->preedit_string)
        g_free(context->preedit_string);
    context->preedit_string = NULL;

    if (context->attrlist)
        pango_attr_list_unref(context->attrlist);
    context->attrlist = NULL;

    G_OBJECT_CLASS(parent_class)->finalize (obj);
}
示例#3
0
static void
fcitx_im_context_focus_out(ClutterIMContext *context)
{
    FcitxLog(LOG_LEVEL, "fcitx_im_context_focus_out");
    FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context);

    if (!fcitxcontext->has_focus) {
        return;
    }

    fcitxcontext->has_focus = false;

    if (IsFcitxIMClientValid(fcitxcontext->client)) {
        FcitxIMClientFocusOut(fcitxcontext->client);
    }


    if (fcitxcontext->preedit_string != NULL)
        g_free(fcitxcontext->preedit_string);
    fcitxcontext->preedit_string = NULL;
    fcitxcontext->cursor_pos = 0;
    g_signal_emit(fcitxcontext, _signal_preedit_changed_id, 0);
    g_signal_emit(fcitxcontext, _signal_preedit_end_id, 0);

    return;
}
示例#4
0
static void
fcitx_im_context_set_client_window(GtkIMContext          *context,
                                   GdkWindow             *client_window)
{
    FcitxLog(LOG_LEVEL, "fcitx_im_context_set_client_window");
    FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context);
    set_ic_client_window(fcitxcontext, client_window);
}
示例#5
0
void _fcitx_im_context_forward_key_cb(FcitxClient* im, guint keyval, guint state, gint type, void* user_data)
{
    FcitxLog(LOG_LEVEL, "_fcitx_im_context_forward_key_cb");
    FcitxIMContext* context =  FCITX_IM_CONTEXT(user_data);
    FcitxKeyEventType tp = (FcitxKeyEventType) type;
    GdkEventKey* event = _create_gdk_event(context, keyval, state, tp);
    event->state |= FcitxKeyState_IgnoredMask;
    gdk_event_put((GdkEvent *)event);
    gdk_event_free((GdkEvent *)event);
}
示例#6
0
static void
fcitx_im_context_set_use_preedit(ClutterIMContext *context,
                                 gboolean      use_preedit)
{
    FcitxLog(LOG_LEVEL, "fcitx_im_context_set_use_preedit");
    FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context);

    fcitxcontext->use_preedit = use_preedit;
    _fcitx_im_context_set_capacity(fcitxcontext);
}
示例#7
0
static void
fcitx_im_context_reset(ClutterIMContext *context)
{
    FcitxLog(LOG_LEVEL, "fcitx_im_context_reset");
    FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context);

    if (IsFcitxIMClientValid(fcitxcontext->client)) {
        FcitxIMClientReset(fcitxcontext->client);
    }
}
示例#8
0
static void
_fcitx_im_context_delete_surrounding_text_cb (FcitxClient* im,
        gint offset_from_cursor,
        guint nchars,
        void* user_data)
{
    FcitxIMContext* context =  FCITX_IM_CONTEXT(user_data);
    gboolean return_value;
    g_signal_emit (context, _signal_delete_surrounding_id, 0, offset_from_cursor, nchars, &return_value);
}
示例#9
0
static void
fcitx_im_context_set_use_preedit(GtkIMContext *context,
                                 gboolean      use_preedit)
{
    FcitxLog(LOG_LEVEL, "fcitx_im_context_set_use_preedit");
    FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context);

    fcitxcontext->use_preedit = use_preedit;
    _fcitx_im_context_set_capacity(fcitxcontext, FALSE);

    gtk_im_context_set_use_preedit(fcitxcontext->slave, use_preedit);
}
示例#10
0
static void
fcitx_im_context_reset(GtkIMContext *context)
{
    FcitxLog(LOG_LEVEL, "fcitx_im_context_reset");
    FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context);

    if (fcitx_client_is_valid(fcitxcontext->client)) {
        fcitx_client_reset(fcitxcontext->client);
    }

    gtk_im_context_reset(fcitxcontext->slave);
}
示例#11
0
void _fcitx_im_context_close_im_cb(FcitxClient* im, void* user_data)
{
    FcitxLog(LOG_LEVEL, "_fcitx_im_context_close_im_cb");
    FcitxIMContext* context =  FCITX_IM_CONTEXT(user_data);

    if (context->preedit_string != NULL)
        g_free(context->preedit_string);
    context->preedit_string = NULL;
    context->cursor_pos = 0;
    g_signal_emit(context, _signal_preedit_changed_id, 0);
    g_signal_emit(context, _signal_preedit_end_id, 0);
}
示例#12
0
static void
fcitx_im_context_finalize(GObject *obj)
{
    FcitxLog(LOG_LEVEL, "fcitx_im_context_finalize");
    FcitxIMContext *context = FCITX_IM_CONTEXT(obj);

    FcitxIMClientClose(context->client);
    context->client = NULL;

    if (context->preedit_string)
        g_free(context->preedit_string);
    context->preedit_string = NULL;
}
示例#13
0
void fcitx_im_context_hide(ClutterIMContext* context)
{
    FcitxLog(LOG_LEVEL, "fcitx_im_context_focus_out");
    FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context);
    
    if (IsFcitxIMClientValid(fcitxcontext->client) && IsFcitxIMClientEnabled(fcitxcontext->client)) {
        FcitxIMClientCloseIC(fcitxcontext->client);
    }

    if (fcitxcontext->has_focus) {
        clutter_im_context_focus_out(context);
    }
}
示例#14
0
void _fcitx_im_context_connect_cb(FcitxIMClient* client, void* user_data)
{
    FcitxIMContext* context =  FCITX_IM_CONTEXT(user_data);
    if (IsFcitxIMClientValid(client)) {
        FcitxIMClientConnectSignal(client,
                                   G_CALLBACK(_fcitx_im_context_enable_im_cb),
                                   G_CALLBACK(_fcitx_im_context_close_im_cb),
                                   G_CALLBACK(_fcitx_im_context_commit_string_cb),
                                   G_CALLBACK(_fcitx_im_context_forward_key_cb),
                                   G_CALLBACK(_fcitx_im_context_update_preedit_cb),
                                   context,
                                   NULL);
        _fcitx_im_context_set_capacity(context);
    }

}
示例#15
0
static void
_fcitx_im_context_update_preedit_cb(DBusGProxy* proxy, char* str, int cursor_pos, void* user_data)
{
    FcitxLog(LOG_LEVEL, "_fcitx_im_context_commit_string_cb");
    FcitxIMContext* context =  FCITX_IM_CONTEXT(user_data);

    gboolean visible = false;

    if (context->preedit_string != NULL) {
        if (strlen(context->preedit_string) != 0)
            visible = true;
        g_free(context->preedit_string);
        context->preedit_string = NULL;
    }
    context->preedit_string = g_strdup(str);
    char* tempstr = g_strndup(str, cursor_pos);
    context->cursor_pos =  fcitx_utf8_strlen(tempstr);
    g_free(tempstr);

    gboolean new_visible = false;

    if (context->preedit_string != NULL) {
        if (strlen(context->preedit_string) != 0)
            new_visible = true;
    }
    gboolean flag = new_visible != visible;

    if (new_visible) {
        if (flag) {
            /* invisible => visible */
            g_signal_emit(context, _signal_preedit_start_id, 0);
        }
        g_signal_emit(context, _signal_preedit_changed_id, 0);
    } else {
        if (flag) {
            /* visible => invisible */
            g_signal_emit(context, _signal_preedit_changed_id, 0);
            g_signal_emit(context, _signal_preedit_end_id, 0);
        } else {
            /* still invisible */
            /* do nothing */
        }
    }

    g_signal_emit(context, _signal_preedit_changed_id, 0);
}
示例#16
0
static void
fcitx_im_context_get_preedit_string(ClutterIMContext   *context,
                                    gchar         **str,
                                    PangoAttrList **attrs,
                                    gint           *cursor_pos)
{
    FcitxLog(LOG_LEVEL, "fcitx_im_context_get_preedit_string");
    FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context);

    if (IsFcitxIMClientValid(fcitxcontext->client) && IsFcitxIMClientEnabled(fcitxcontext->client)) {
        if (str) {
            if (fcitxcontext->preedit_string)
                *str = strdup(fcitxcontext->preedit_string);
            else
                *str = strdup("");
        }
        if (attrs) {
            *attrs = pango_attr_list_new();

            if (str) {
                PangoAttribute *pango_attr;
                pango_attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
                pango_attr->start_index = 0;
                pango_attr->end_index = strlen(*str);
                pango_attr_list_insert(*attrs, pango_attr);
            }
        }
        if (cursor_pos)
            *cursor_pos = fcitxcontext->cursor_pos;

    } else {
        if (str) {
            *str = g_strdup("");
        }
        if (attrs) {
            *attrs = pango_attr_list_new();
        }
        if (cursor_pos)
            *cursor_pos = 0;
    }
    return ;
}
示例#17
0
static void
fcitx_im_context_set_cursor_location(ClutterIMContext *context,
                                     ClutterIMRectangle *area)
{
    FcitxLog(LOG_LEVEL, "fcitx_im_context_set_cursor_location %d %d %d %d", area->x, area->y, area->height, area->width);
    FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context);

    if (fcitxcontext->area.x == area->x &&
            fcitxcontext->area.y == area->y &&
            fcitxcontext->area.width == area->width &&
            fcitxcontext->area.height == area->height) {
        return;
    }
    fcitxcontext->area = *area;

    if (IsFcitxIMClientValid(fcitxcontext->client)) {
        _set_cursor_location_internal(fcitxcontext);
    }

    return;
}
示例#18
0
static void
fcitx_im_context_focus_in(GtkIMContext *context)
{
    FcitxLog(LOG_LEVEL, "fcitx_im_context_focus_in");
    FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context);

    if (fcitxcontext->has_focus)
        return;

    _fcitx_im_context_set_capacity(fcitxcontext, FALSE);

    fcitxcontext->has_focus = true;

    if (_focus_im_context != NULL) {
        g_assert (_focus_im_context != context);
        gtk_im_context_focus_out (_focus_im_context);
        g_assert (_focus_im_context == NULL);
    }

    if (fcitx_client_is_valid(fcitxcontext->client)) {
        fcitx_client_focus_in(fcitxcontext->client);
    }

    gtk_im_context_focus_in(fcitxcontext->slave);

    /* set_cursor_location_internal() will get origin from X server,
     * it blocks UI. So delay it to idle callback. */
    g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
                    (GSourceFunc) _set_cursor_location_internal,
                    g_object_ref(fcitxcontext),
                    (GDestroyNotify) g_object_unref);

    _request_surrounding_text (fcitxcontext);

    g_object_add_weak_pointer ((GObject *) context,
                               (gpointer *) &_focus_im_context);
    _focus_im_context = context;

    return;
}
示例#19
0
static void
fcitx_im_context_get_preedit_string(GtkIMContext   *context,
                                    gchar         **str,
                                    PangoAttrList **attrs,
                                    gint           *cursor_pos)
{
    FcitxLog(LOG_LEVEL, "fcitx_im_context_get_preedit_string");
    FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context);

    if (fcitx_client_is_valid(fcitxcontext->client)) {
        if (str) {
            if (fcitxcontext->preedit_string)
                *str = strdup(fcitxcontext->preedit_string);
            else
                *str = strdup("");
        }
        if (attrs) {
            if (fcitxcontext->attrlist == NULL) {
                *attrs = pango_attr_list_new();

                if (str) {
                    PangoAttribute *pango_attr;
                    pango_attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
                    pango_attr->start_index = 0;
                    pango_attr->end_index = strlen(*str);
                    pango_attr_list_insert(*attrs, pango_attr);
                }
            }
            else {
                *attrs = pango_attr_list_ref (fcitxcontext->attrlist);
            }
        }
        if (cursor_pos)
            *cursor_pos = fcitxcontext->cursor_pos;

    } else
        gtk_im_context_get_preedit_string(fcitxcontext->slave, str, attrs, cursor_pos);
    return ;
}
示例#20
0
static gboolean
fcitx_im_context_filter_keypress(ClutterIMContext *context,
                                 ClutterKeyEvent  *event)
{
    FcitxLog(LOG_LEVEL, "fcitx_im_context_filter_keypress");
    FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context);

    if (G_UNLIKELY(event->modifier_state & FcitxKeyState_HandledMask))
        return TRUE;

    if (G_UNLIKELY(event->modifier_state & FcitxKeyState_IgnoredMask))
        return FALSE;

    if (IsFcitxIMClientValid(fcitxcontext->client) && fcitxcontext->has_focus) {
        if (!IsFcitxIMClientEnabled(fcitxcontext->client)) {
            if (!FcitxIsHotKey(event->keyval, event->modifier_state, FcitxIMClientGetTriggerKey(fcitxcontext->client)))
                return FALSE;
        }

        fcitxcontext->time = event->time;

        int ret = FcitxIMClientProcessKeySync(fcitxcontext->client,
                                                event->keyval,
                                                event->hardware_keycode,
                                                event->modifier_state,
                                                (event->type == CLUTTER_KEY_PRESS) ? (FCITX_PRESS_KEY) : (FCITX_RELEASE_KEY),
                                                event->time);
        if (ret <= 0) {
            event->modifier_state |= FcitxKeyState_IgnoredMask;
            return FALSE;
        } else {
            event->modifier_state |= FcitxKeyState_HandledMask;
            return TRUE;
        }
    } else {
        return FALSE;
    }
    return FALSE;
}
示例#21
0
static void
fcitx_im_context_set_cursor_location(GtkIMContext *context,
                                     GdkRectangle *area)
{
    FcitxLog(LOG_LEVEL, "fcitx_im_context_set_cursor_location %d %d %d %d", area->x, area->y, area->height, area->width);
    FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context);

    if (fcitxcontext->area.x == area->x &&
            fcitxcontext->area.y == area->y &&
            fcitxcontext->area.width == area->width &&
            fcitxcontext->area.height == area->height) {
        return;
    }
    fcitxcontext->area = *area;

    if (fcitx_client_is_valid(fcitxcontext->client)) {
        _set_cursor_location_internal(fcitxcontext);
    }
    gtk_im_context_set_cursor_location(fcitxcontext->slave, area);

    return;
}
示例#22
0
static void
fcitx_im_context_set_surrounding (GtkIMContext *context,
                                  const gchar *text,
                                  gint len,
                                  gint cursor_index)
{
    g_return_if_fail (context != NULL);
    g_return_if_fail (FCITX_IS_IM_CONTEXT (context));
    g_return_if_fail (text != NULL);
    g_return_if_fail (strlen (text) >= len);
    g_return_if_fail (0 <= cursor_index && cursor_index <= len);

    FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT (context);

    if (fcitx_client_is_valid(fcitxcontext->client) && !(fcitxcontext->capacity & CAPACITY_PASSWORD)) {
        guint cursor_pos;
        guint utf8_len;
        gchar *p;

        p = g_strndup (text, len);
        cursor_pos = g_utf8_strlen (p, cursor_index);
        utf8_len = g_utf8_strlen(p, len);

        guint anchor_pos = get_selection_anchor_point (fcitxcontext,
                           cursor_pos,
                           utf8_len);
        fcitx_client_set_surrounding_text (fcitxcontext->client,
                                           p,
                                           cursor_pos,
                                           anchor_pos);
        g_free (p);
    }
    gtk_im_context_set_surrounding (fcitxcontext->slave,
                                    text,
                                    len,
                                    cursor_index);
}
示例#23
0
static void
fcitx_im_context_focus_in(ClutterIMContext *context)
{
    FcitxLog(LOG_LEVEL, "fcitx_im_context_focus_in");
    FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context);

    if (fcitxcontext->has_focus)
        return;

    fcitxcontext->has_focus = true;

    if (IsFcitxIMClientValid(fcitxcontext->client)) {
        FcitxIMClientFocusIn(fcitxcontext->client);
    }

    /* set_cursor_location_internal() will get origin from X server,
     * it blocks UI. So delay it to idle callback. */
    g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
                    (GSourceFunc) _set_cursor_location_internal,
                    g_object_ref(fcitxcontext),
                    (GDestroyNotify) g_object_unref);

    return;
}
示例#24
0
void _fcitx_im_context_commit_string_cb(DBusGProxy* proxy, char* str, void* user_data)
{
    FcitxLog(LOG_LEVEL, "_fcitx_im_context_commit_string_cb");
    FcitxIMContext* context =  FCITX_IM_CONTEXT(user_data);
    g_signal_emit(context, _signal_commit_id, 0, str);
}
示例#25
0
void _fcitx_im_context_enable_im_cb(DBusGProxy* proxy, void* user_data)
{
    FcitxLog(LOG_LEVEL, "_fcitx_im_context_enable_im_cb");
    FcitxIMContext* context =  FCITX_IM_CONTEXT(user_data);
    FcitxIMClientSetEnabled(context->client, true);
}
示例#26
0
/* Copy from gdk */
static GdkEventKey *
_create_gdk_event(FcitxIMContext *fcitxcontext,
                  guint keyval,
                  guint state,
                  FcitxKeyEventType type
                 )
{
    gunichar c = 0;
    gchar buf[8];

    GdkEventKey *event = (GdkEventKey *)gdk_event_new((type == FCITX_RELEASE_KEY) ? GDK_KEY_RELEASE : GDK_KEY_PRESS);

    if (fcitxcontext && fcitxcontext->client_window)
        event->window = g_object_ref(fcitxcontext->client_window);

    /* The time is copied the latest value from the previous
     * GdkKeyEvent in filter_keypress().
     *
     * We understand the best way would be to pass the all time value
     * to Fcitx functions process_key_event() and Fcitx DBus functions
     * ProcessKeyEvent() in IM clients and IM engines so that the
     * _create_gdk_event() could get the correct time values.
     * However it would causes to change many functions and the time value
     * would not provide the useful meanings for each Fcitx engines but just
     * pass the original value to ForwardKeyEvent().
     * We use the saved value at the moment.
     *
     * Another idea might be to have the time implementation in X servers
     * but some Xorg uses clock_gettime() and others use gettimeofday()
     * and the values would be different in each implementation and
     * locale/remote X server. So probably that idea would not work. */
    if (fcitxcontext) {
        event->time = fcitxcontext->time;
    } else {
        event->time = GDK_CURRENT_TIME;
    }

    event->send_event = FALSE;
    event->state = state;
    event->keyval = keyval;
    event->string = NULL;
    event->length = 0;
    event->hardware_keycode = 0;
    if (event->window) {
#ifndef NEW_GDK_WINDOW_GET_DISPLAY
        GdkDisplay      *display = gdk_display_get_default();
#else
        GdkDisplay      *display = gdk_window_get_display(event->window);
#endif
        GdkKeymap       *keymap  = gdk_keymap_get_for_display(display);
        GdkKeymapKey    *keys;
        gint             n_keys = 0;

        if (gdk_keymap_get_entries_for_keyval(keymap, keyval, &keys, &n_keys)) {
            if (n_keys)
                event->hardware_keycode = keys[0].keycode;
            g_free(keys);
        }
    }

    event->group = 0;
    event->is_modifier = _key_is_modifier(keyval);

#ifdef DEPRECATED_GDK_KEYSYMS
    if (keyval != GDK_VoidSymbol)
#else
    if (keyval != GDK_KEY_VoidSymbol)
#endif
        c = gdk_keyval_to_unicode(keyval);

    if (c) {
        gsize bytes_written;
        gint len;

        /* Apply the control key - Taken from Xlib
        */
        if (event->state & GDK_CONTROL_MASK) {
            if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
            else if (c == '2') {
                event->string = g_memdup("\0\0", 2);
                event->length = 1;
                buf[0] = '\0';
                goto out;
            } else if (c >= '3' && c <= '7') c -= ('3' - '\033');
            else if (c == '8') c = '\177';
            else if (c == '/') c = '_' & 0x1F;
        }

        len = g_unichar_to_utf8(c, buf);
        buf[len] = '\0';

        event->string = g_locale_from_utf8(buf, len,
                                           NULL, &bytes_written,
                                           NULL);
        if (event->string)
            event->length = bytes_written;
#ifdef DEPRECATED_GDK_KEYSYMS
    } else if (keyval == GDK_Escape) {
#else
    } else if (keyval == GDK_KEY_Escape) {
#endif
        event->length = 1;
        event->string = g_strdup("\033");
    }
#ifdef DEPRECATED_GDK_KEYSYMS
    else if (keyval == GDK_Return ||
             keyval == GDK_KP_Enter) {
#else
    else if (keyval == GDK_KEY_Return ||
             keyval == GDK_KEY_KP_Enter) {
#endif
        event->length = 1;
        event->string = g_strdup("\r");
    }

    if (!event->string) {
        event->length = 0;
        event->string = g_strdup("");
    }
out:
    return event;
}


static gboolean
_key_is_modifier(guint keyval)
{
    /* See gdkkeys-x11.c:_gdk_keymap_key_is_modifier() for how this
    * really should be implemented */

    switch (keyval) {
#ifdef DEPRECATED_GDK_KEYSYMS
    case GDK_Shift_L:
    case GDK_Shift_R:
    case GDK_Control_L:
    case GDK_Control_R:
    case GDK_Caps_Lock:
    case GDK_Shift_Lock:
    case GDK_Meta_L:
    case GDK_Meta_R:
    case GDK_Alt_L:
    case GDK_Alt_R:
    case GDK_Super_L:
    case GDK_Super_R:
    case GDK_Hyper_L:
    case GDK_Hyper_R:
    case GDK_ISO_Lock:
    case GDK_ISO_Level2_Latch:
    case GDK_ISO_Level3_Shift:
    case GDK_ISO_Level3_Latch:
    case GDK_ISO_Level3_Lock:
    case GDK_ISO_Group_Shift:
    case GDK_ISO_Group_Latch:
    case GDK_ISO_Group_Lock:
        return TRUE;
#else
    case GDK_KEY_Shift_L:
    case GDK_KEY_Shift_R:
    case GDK_KEY_Control_L:
    case GDK_KEY_Control_R:
    case GDK_KEY_Caps_Lock:
    case GDK_KEY_Shift_Lock:
    case GDK_KEY_Meta_L:
    case GDK_KEY_Meta_R:
    case GDK_KEY_Alt_L:
    case GDK_KEY_Alt_R:
    case GDK_KEY_Super_L:
    case GDK_KEY_Super_R:
    case GDK_KEY_Hyper_L:
    case GDK_KEY_Hyper_R:
    case GDK_KEY_ISO_Lock:
    case GDK_KEY_ISO_Level2_Latch:
    case GDK_KEY_ISO_Level3_Shift:
    case GDK_KEY_ISO_Level3_Latch:
    case GDK_KEY_ISO_Level3_Lock:
    case GDK_KEY_ISO_Level5_Shift:
    case GDK_KEY_ISO_Level5_Latch:
    case GDK_KEY_ISO_Level5_Lock:
    case GDK_KEY_ISO_Group_Shift:
    case GDK_KEY_ISO_Group_Latch:
    case GDK_KEY_ISO_Group_Lock:
        return TRUE;
#endif
    default:
        return FALSE;
    }
}

void _fcitx_im_context_connect_cb(FcitxClient* im, void* user_data)
{
    FcitxIMContext* context =  FCITX_IM_CONTEXT(user_data);
    _fcitx_im_context_set_capacity(context, TRUE);
    /* set_cursor_location_internal() will get origin from X server,
     * it blocks UI. So delay it to idle callback. */
    g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
                    (GSourceFunc) _set_cursor_location_internal,
                    g_object_ref(context),
                    (GDestroyNotify) g_object_unref);
}
示例#27
0
static gboolean
fcitx_im_context_filter_keypress(GtkIMContext *context,
                                 GdkEventKey  *event)
{
    FcitxLog(LOG_LEVEL, "fcitx_im_context_filter_keypress");
    FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context);

    /* check this first, since we use key snooper, most key will be handled. */
    if (fcitx_client_is_valid(fcitxcontext->client) ) {
        /* XXX it is a workaround for some applications do not set client window. */
        if (fcitxcontext->client_window == NULL && event->window != NULL) {
            gtk_im_context_set_client_window((GtkIMContext *)fcitxcontext, event->window);

            /* set_cursor_location_internal() will get origin from X server,
            * it blocks UI. So delay it to idle callback. */
            g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
                            (GSourceFunc) _set_cursor_location_internal,
                            g_object_ref(fcitxcontext),
                            (GDestroyNotify) g_object_unref);
        }
    }

    if (G_UNLIKELY(event->state & FcitxKeyState_HandledMask))
        return TRUE;

    if (G_UNLIKELY(event->state & FcitxKeyState_IgnoredMask))
        return gtk_im_context_filter_keypress(fcitxcontext->slave, event);

    if (fcitx_client_is_valid(fcitxcontext->client) && fcitxcontext->has_focus) {
        _request_surrounding_text (fcitxcontext);

        fcitxcontext->time = event->time;

        if (_use_sync_mode) {
            int ret = fcitx_client_process_key_sync(fcitxcontext->client,
                                                    event->keyval,
                                                    event->hardware_keycode,
                                                    event->state,
                                                    (event->type == GDK_KEY_PRESS) ? (FCITX_PRESS_KEY) : (FCITX_RELEASE_KEY),
                                                    event->time);
            if (ret <= 0) {
                event->state |= FcitxKeyState_IgnoredMask;
                return gtk_im_context_filter_keypress(fcitxcontext->slave, event);
            } else {
                event->state |= FcitxKeyState_HandledMask;
                return TRUE;
            }
        } else {
            ProcessKeyStruct* pks = g_malloc0(sizeof(ProcessKeyStruct));
            pks->context = fcitxcontext;
            pks->event = (GdkEventKey *)  gdk_event_copy((GdkEvent *) event);

            fcitx_client_process_key(fcitxcontext->client,
                                     _fcitx_im_context_process_key_cb,
                                     pks,
                                     event->keyval,
                                     event->hardware_keycode,
                                     event->state,
                                     (event->type == GDK_KEY_PRESS) ? (FCITX_PRESS_KEY) : (FCITX_RELEASE_KEY),
                                     event->time);
            event->state |= FcitxKeyState_HandledMask;
            return TRUE;
        }
    } else {
        return gtk_im_context_filter_keypress(fcitxcontext->slave, event);
    }
    return FALSE;
}
示例#28
0
static void
_fcitx_im_context_update_formatted_preedit_cb(FcitxClient* im, GPtrArray* array, int cursor_pos, void* user_data)
{
    FcitxLog(LOG_LEVEL, "_fcitx_im_context_commit_string_cb");
    FcitxIMContext* context =  FCITX_IM_CONTEXT(user_data);

    gboolean visible = false;

    if (context->preedit_string != NULL) {
        if (strlen(context->preedit_string) != 0)
            visible = true;
        g_free(context->preedit_string);
        context->preedit_string = NULL;
    }

    if (context->attrlist != NULL) {
        pango_attr_list_unref(context->attrlist);
    }

    context->attrlist = pango_attr_list_new();

    GString* gstr = g_string_new(NULL);

    int i = 0;
    for (i = 0; i < array->len; i++) {
        size_t bytelen = strlen(gstr->str);
        FcitxPreeditItem* preedit = g_ptr_array_index(array, i);
        const gchar* s = preedit->string;
        gint type = preedit->type;

        PangoAttribute *pango_attr = NULL;
        if ((type & MSG_NOUNDERLINE) == 0) {
            pango_attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
            pango_attr->start_index = bytelen;
            pango_attr->end_index = bytelen + strlen(s);
            pango_attr_list_insert(context->attrlist, pango_attr);
        }

        if (type & MSG_HIGHLIGHT) {
            gboolean hasColor;
            GdkColor fg;
            GdkColor bg;

            if (context->client_window) {
                GtkWidget *widget;
                gdk_window_get_user_data (context->client_window,
                                          (gpointer *)&widget);
                if (GTK_IS_WIDGET(widget)) {
                    hasColor = true;
                    GtkStyle* style = gtk_widget_get_style(widget);
                    fg = style->text[GTK_STATE_SELECTED];
                    bg = style->bg[GTK_STATE_SELECTED];
                }
            }

            if (!hasColor) {
                fg.red = 0xffff;
                fg.green = 0xffff;
                fg.blue = 0xffff;
                bg.red = 0x43ff;
                bg.green = 0xacff;
                bg.blue = 0xe8ff;
            }

            pango_attr = pango_attr_foreground_new(fg.red, fg.green, fg.blue);
            pango_attr->start_index = bytelen;
            pango_attr->end_index = bytelen + strlen(s);
            pango_attr_list_insert(context->attrlist, pango_attr);
            pango_attr = pango_attr_background_new(bg.red, bg.green, bg.blue);
            pango_attr->start_index = bytelen;
            pango_attr->end_index = bytelen + strlen(s);
            pango_attr_list_insert(context->attrlist, pango_attr);
        }
        gstr = g_string_append(gstr, s);
    }

    gchar* str = g_string_free(gstr, FALSE);

    context->preedit_string = g_strdup(str);
    char* tempstr = g_strndup(str, cursor_pos);
    context->cursor_pos =  fcitx_utf8_strlen(tempstr);
    g_free(tempstr);

    gboolean new_visible = false;

    if (context->preedit_string != NULL) {
        if (strlen(context->preedit_string) != 0)
            new_visible = true;
    }
    gboolean flag = new_visible != visible;

    if (new_visible) {
        if (flag) {
            /* invisible => visible */
            g_signal_emit(context, _signal_preedit_start_id, 0);
        }
        g_signal_emit(context, _signal_preedit_changed_id, 0);
    } else {
        if (flag) {
            /* visible => invisible */
            g_signal_emit(context, _signal_preedit_changed_id, 0);
            g_signal_emit(context, _signal_preedit_end_id, 0);
        } else {
            /* still invisible */
            /* do nothing */
        }
    }

    g_signal_emit(context, _signal_preedit_changed_id, 0);
}
示例#29
0
FcitxIMContext *
fcitx_im_context_new(void)
{
    GObject *obj = g_object_new(FCITX_TYPE_IM_CONTEXT, NULL);
    return FCITX_IM_CONTEXT(obj);
}