Blame src/ibushotkey.c

Packit 3ff832
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
Packit 3ff832
/* vim:set et sts=4: */
Packit 3ff832
/* IBus - The Input Bus
Packit 3ff832
 * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
Packit 3ff832
 * Copyright (C) 2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
Packit 3ff832
 * Copyright (C) 2008-2018 Red Hat, Inc.
Packit 3ff832
 *
Packit 3ff832
 * This library is free software; you can redistribute it and/or
Packit 3ff832
 * modify it under the terms of the GNU Lesser General Public
Packit 3ff832
 * License as published by the Free Software Foundation; either
Packit 3ff832
 * version 2.1 of the License, or (at your option) any later version.
Packit 3ff832
 *
Packit 3ff832
 * This library is distributed in the hope that it will be useful,
Packit 3ff832
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 3ff832
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 3ff832
 * Lesser General Public License for more details.
Packit 3ff832
 *
Packit 3ff832
 * You should have received a copy of the GNU Lesser General Public
Packit 3ff832
 * License along with this library; if not, write to the Free Software
Packit 3ff832
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
Packit 3ff832
 * USA
Packit 3ff832
 */
Packit 3ff832
#include "ibushotkey.h"
Packit 3ff832
#include "ibusmarshalers.h"
Packit 3ff832
#include "ibuskeysyms.h"
Packit 3ff832
#include "ibusinternal.h"
Packit 3ff832
#include "ibusshare.h"
Packit 3ff832
Packit 3ff832
#define IBUS_HOTKEY_PROFILE_GET_PRIVATE(o)  \
Packit 3ff832
   (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_HOTKEY_PROFILE, IBusHotkeyProfilePrivate))
Packit 3ff832
Packit 3ff832
enum {
Packit 3ff832
    TRIGGER,
Packit 3ff832
    LAST_SIGNAL,
Packit 3ff832
};
Packit 3ff832
Packit 3ff832
typedef struct _IBusHotkey IBusHotkey;
Packit 3ff832
typedef struct _IBusHotkeyEvent IBusHotkeyEvent;
Packit 3ff832
typedef struct _IBusHotkeyProfilePrivate IBusHotkeyProfilePrivate;
Packit 3ff832
Packit 3ff832
struct _IBusHotkey {
Packit 3ff832
    guint   keyval;
Packit 3ff832
    guint   modifiers;
Packit 3ff832
};
Packit 3ff832
Packit 3ff832
struct _IBusHotkeyEvent {
Packit 3ff832
    GQuark event;
Packit 3ff832
    GList *hotkeys;
Packit 3ff832
};
Packit 3ff832
Packit 3ff832
struct _IBusHotkeyProfilePrivate {
Packit 3ff832
    GTree *hotkeys;
Packit 3ff832
    GArray *events;
Packit 3ff832
    guint   mask;
Packit 3ff832
};
Packit 3ff832
Packit 3ff832
Packit 3ff832
Packit 3ff832
/* functions prototype */
Packit 3ff832
static IBusHotkey   *ibus_hotkey_new                (guint                   keyval,
Packit 3ff832
                                                     guint                   modifiers);
Packit 3ff832
static IBusHotkey   *ibus_hotkey_copy               (const IBusHotkey       *src);
Packit 3ff832
static void          ibus_hotkey_free               (IBusHotkey             *hotkey);
Packit 3ff832
static void          ibus_hotkey_profile_class_init (IBusHotkeyProfileClass *class);
Packit 3ff832
static void          ibus_hotkey_profile_init       (IBusHotkeyProfile      *profile);
Packit 3ff832
static void          ibus_hotkey_profile_destroy    (IBusHotkeyProfile      *profile);
Packit 3ff832
static gboolean      ibus_hotkey_profile_serialize  (IBusHotkeyProfile      *profile,
Packit 3ff832
                                                     GVariantBuilder        *builder);
Packit 3ff832
static gint          ibus_hotkey_profile_deserialize(IBusHotkeyProfile      *profile,
Packit 3ff832
                                                     GVariant               *variant);
Packit 3ff832
static gboolean      ibus_hotkey_profile_copy       (IBusHotkeyProfile      *dest,
Packit 3ff832
                                                     const IBusHotkeyProfile*src);
Packit 3ff832
static void          ibus_hotkey_profile_trigger    (IBusHotkeyProfile      *profile,
Packit 3ff832
                                                     GQuark                  event,
Packit 3ff832
                                                     gpointer                user_data);
Packit 3ff832
Packit 3ff832
// Normalize modifiers by setting necessary modifier bits according to keyval.
Packit 3ff832
static guint         normalize_modifiers            (guint                   keyval,
Packit 3ff832
                                                     guint                   modifiers);
Packit 3ff832
static gboolean      is_modifier                    (guint                   keyval);
Packit 3ff832
Packit 3ff832
static IBusSerializableClass *parent_class = NULL;
Packit 3ff832
Packit 3ff832
static guint profile_signals[LAST_SIGNAL] = { 0 };
Packit 3ff832
Packit 3ff832
GType
Packit 3ff832
ibus_hotkey_get_type (void)
Packit 3ff832
{
Packit 3ff832
    static GType type = 0;
Packit 3ff832
Packit 3ff832
    if (type == 0) {
Packit 3ff832
        type = g_boxed_type_register_static ("IBusHotkey",
Packit 3ff832
                                             (GBoxedCopyFunc) ibus_hotkey_copy,
Packit 3ff832
                                             (GBoxedFreeFunc) ibus_hotkey_free);
Packit 3ff832
    }
Packit 3ff832
Packit 3ff832
    return type;
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static IBusHotkey *
Packit 3ff832
ibus_hotkey_new (guint keyval,
Packit 3ff832
                 guint modifiers)
Packit 3ff832
{
Packit 3ff832
    IBusHotkey *hotkey = g_slice_new (IBusHotkey);
Packit 3ff832
Packit 3ff832
    hotkey->keyval = keyval;
Packit 3ff832
    hotkey->modifiers = modifiers;
Packit 3ff832
Packit 3ff832
    return hotkey;
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static void
Packit 3ff832
ibus_hotkey_free (IBusHotkey *hotkey)
Packit 3ff832
{
Packit 3ff832
    g_slice_free (IBusHotkey, hotkey);
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
Packit 3ff832
static IBusHotkey *
Packit 3ff832
ibus_hotkey_copy (const IBusHotkey *src)
Packit 3ff832
{
Packit 3ff832
    return ibus_hotkey_new (src->keyval, src->modifiers);
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static gint
Packit 3ff832
ibus_hotkey_cmp_with_data (IBusHotkey *hotkey1,
Packit 3ff832
                           IBusHotkey *hotkey2,
Packit 3ff832
                           gpointer    user_data)
Packit 3ff832
{
Packit 3ff832
    gint retval;
Packit 3ff832
Packit 3ff832
    if (hotkey1 == hotkey2)
Packit 3ff832
        return 0;
Packit 3ff832
Packit 3ff832
    retval = hotkey1->keyval - hotkey2->keyval;
Packit 3ff832
    if (retval == 0)
Packit 3ff832
        retval = hotkey1->modifiers - hotkey2->modifiers;
Packit 3ff832
Packit 3ff832
    return retval;
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
Packit 3ff832
Packit 3ff832
GType
Packit 3ff832
ibus_hotkey_profile_get_type (void)
Packit 3ff832
{
Packit 3ff832
    static GType type = 0;
Packit 3ff832
Packit 3ff832
    static const GTypeInfo type_info = {
Packit 3ff832
        sizeof (IBusHotkeyProfileClass),
Packit 3ff832
        (GBaseInitFunc)     NULL,
Packit 3ff832
        (GBaseFinalizeFunc) NULL,
Packit 3ff832
        (GClassInitFunc)    ibus_hotkey_profile_class_init,
Packit 3ff832
        NULL,               /* class finialize */
Packit 3ff832
        NULL,               /* class data */
Packit 3ff832
        sizeof (IBusHotkeyProfile),
Packit 3ff832
        0,
Packit 3ff832
        (GInstanceInitFunc) ibus_hotkey_profile_init,
Packit 3ff832
    };
Packit 3ff832
Packit 3ff832
    if (type == 0) {
Packit 3ff832
        type = g_type_register_static (IBUS_TYPE_SERIALIZABLE,
Packit 3ff832
                                       "IBusHotkeyProfile",
Packit 3ff832
                                       &type_info,
Packit 3ff832
                                       0);
Packit 3ff832
    }
Packit 3ff832
Packit 3ff832
    return type;
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static void
Packit 3ff832
ibus_hotkey_profile_class_init (IBusHotkeyProfileClass *class)
Packit 3ff832
{
Packit 3ff832
    IBusObjectClass *object_class = IBUS_OBJECT_CLASS (class);
Packit 3ff832
    IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (class);
Packit 3ff832
Packit 3ff832
    parent_class = (IBusSerializableClass *) g_type_class_peek_parent (class);
Packit 3ff832
Packit 3ff832
    g_type_class_add_private (class, sizeof (IBusHotkeyProfilePrivate));
Packit 3ff832
Packit 3ff832
    object_class->destroy = (IBusObjectDestroyFunc) ibus_hotkey_profile_destroy;
Packit 3ff832
Packit 3ff832
    serializable_class->serialize   = (IBusSerializableSerializeFunc) ibus_hotkey_profile_serialize;
Packit 3ff832
    serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_hotkey_profile_deserialize;
Packit 3ff832
    serializable_class->copy        = (IBusSerializableCopyFunc) ibus_hotkey_profile_copy;
Packit 3ff832
Packit 3ff832
    class->trigger = ibus_hotkey_profile_trigger;
Packit 3ff832
Packit 3ff832
    /* install signals */
Packit 3ff832
    /**
Packit 3ff832
     * IBusHotkeyProfile::trigger:
Packit 3ff832
     * @profile: An IBusHotkeyProfile.
Packit 3ff832
     * @event: An event in GQuark.
Packit 3ff832
     * @user_data: User data for callback.
Packit 3ff832
     *
Packit 3ff832
     * Emitted when a hotkey is pressed and the hotkey is in profile.
Packit 3ff832
     * Implement the member function trigger() in extended class to receive this signal.
Packit 3ff832
     *
Packit 3ff832
     * <note><para>The last parameter, user_data is not actually a valid parameter. It is displayed because of GtkDoc bug.</para></note>
Packit 3ff832
     */
Packit 3ff832
    profile_signals[TRIGGER] =
Packit 3ff832
        g_signal_new (I_("trigger"),
Packit 3ff832
            G_TYPE_FROM_CLASS (class),
Packit 3ff832
            G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
Packit 3ff832
            G_STRUCT_OFFSET (IBusHotkeyProfileClass, trigger),
Packit 3ff832
            NULL, NULL,
Packit 3ff832
            _ibus_marshal_VOID__UINT_POINTER,
Packit 3ff832
            G_TYPE_NONE,
Packit 3ff832
            2,
Packit 3ff832
            G_TYPE_UINT,
Packit 3ff832
            G_TYPE_POINTER);
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static void
Packit 3ff832
ibus_hotkey_profile_init (IBusHotkeyProfile *profile)
Packit 3ff832
{
Packit 3ff832
    IBusHotkeyProfilePrivate *priv;
Packit 3ff832
    priv = IBUS_HOTKEY_PROFILE_GET_PRIVATE (profile);
Packit 3ff832
Packit 3ff832
    priv->hotkeys = g_tree_new_full ((GCompareDataFunc) ibus_hotkey_cmp_with_data,
Packit 3ff832
                                     NULL,
Packit 3ff832
                                     (GDestroyNotify) ibus_hotkey_free,
Packit 3ff832
                                     NULL);
Packit 3ff832
    priv->events = g_array_new (TRUE, TRUE, sizeof (IBusHotkeyEvent));
Packit 3ff832
Packit 3ff832
    priv->mask = IBUS_SHIFT_MASK |
Packit 3ff832
                 IBUS_CONTROL_MASK |
Packit 3ff832
                 IBUS_MOD1_MASK |
Packit 3ff832
                 IBUS_SUPER_MASK |
Packit 3ff832
                 IBUS_HYPER_MASK |
Packit 3ff832
                 IBUS_RELEASE_MASK;
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static void
Packit 3ff832
ibus_hotkey_profile_destroy (IBusHotkeyProfile *profile)
Packit 3ff832
{
Packit 3ff832
    IBusHotkeyProfilePrivate *priv;
Packit 3ff832
    priv = IBUS_HOTKEY_PROFILE_GET_PRIVATE (profile);
Packit 3ff832
Packit 3ff832
    /* free events */
Packit 3ff832
    if (priv->events) {
Packit 3ff832
        IBusHotkeyEvent *p;
Packit 3ff832
        gint i;
Packit 3ff832
        p = (IBusHotkeyEvent *)g_array_free (priv->events, FALSE);
Packit 3ff832
        priv->events = NULL;
Packit 3ff832
Packit 3ff832
        for (i = 0; p[i].event != 0; i++) {
Packit 3ff832
            g_list_free (p[i].hotkeys);
Packit 3ff832
        }
Packit 3ff832
        g_free (p);
Packit 3ff832
    }
Packit 3ff832
Packit 3ff832
    if (priv->hotkeys) {
Packit 3ff832
        g_tree_destroy (priv->hotkeys);
Packit 3ff832
        priv->hotkeys = NULL;
Packit 3ff832
    }
Packit 3ff832
Packit 3ff832
    IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *)profile);
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static gboolean
Packit 3ff832
ibus_hotkey_profile_serialize (IBusHotkeyProfile *profile,
Packit 3ff832
                               GVariantBuilder   *builder)
Packit 3ff832
{
Packit 3ff832
    gboolean retval;
Packit 3ff832
Packit 3ff832
    retval = parent_class->serialize ((IBusSerializable *) profile, builder);
Packit 3ff832
    g_return_val_if_fail (retval, FALSE);
Packit 3ff832
Packit 3ff832
    return TRUE;
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static gint
Packit 3ff832
ibus_hotkey_profile_deserialize (IBusHotkeyProfile *profile,
Packit 3ff832
                                 GVariant          *variant)
Packit 3ff832
{
Packit 3ff832
    gint retval;
Packit 3ff832
Packit 3ff832
    retval = parent_class->deserialize ((IBusSerializable *) profile, variant);
Packit 3ff832
    g_return_val_if_fail (retval, 0);
Packit 3ff832
Packit 3ff832
    return retval;
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static gboolean
Packit 3ff832
ibus_hotkey_profile_copy (IBusHotkeyProfile       *dest,
Packit 3ff832
                          const IBusHotkeyProfile *src)
Packit 3ff832
{
Packit 3ff832
    gboolean retval;
Packit 3ff832
Packit 3ff832
    retval = parent_class->copy ((IBusSerializable *)dest,
Packit 3ff832
                                 (IBusSerializable *)src);
Packit 3ff832
    g_return_val_if_fail (retval, FALSE);
Packit 3ff832
Packit 3ff832
    g_return_val_if_fail (IBUS_IS_HOTKEY_PROFILE (dest), FALSE);
Packit 3ff832
    g_return_val_if_fail (IBUS_IS_HOTKEY_PROFILE (src), FALSE);
Packit 3ff832
Packit 3ff832
    return TRUE;
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
IBusHotkeyProfile *
Packit 3ff832
ibus_hotkey_profile_new (void)
Packit 3ff832
{
Packit 3ff832
    IBusHotkeyProfile *profile = g_object_new (IBUS_TYPE_HOTKEY_PROFILE, NULL);
Packit 3ff832
Packit 3ff832
    return profile;
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static void
Packit 3ff832
ibus_hotkey_profile_trigger (IBusHotkeyProfile *profile,
Packit 3ff832
                             GQuark             event,
Packit 3ff832
                             gpointer           user_data)
Packit 3ff832
{
Packit 3ff832
    // g_debug ("%s is triggerred", g_quark_to_string (event));
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static guint
Packit 3ff832
normalize_modifiers (guint keyval,
Packit 3ff832
                     guint modifiers)
Packit 3ff832
{
Packit 3ff832
    switch(keyval) {
Packit 3ff832
    case IBUS_KEY_Control_L:
Packit 3ff832
    case IBUS_KEY_Control_R:
Packit 3ff832
        return modifiers | IBUS_CONTROL_MASK;
Packit 3ff832
    case IBUS_KEY_Shift_L:
Packit 3ff832
    case IBUS_KEY_Shift_R:
Packit 3ff832
        return modifiers | IBUS_SHIFT_MASK;
Packit 3ff832
    case IBUS_KEY_Alt_L:
Packit 3ff832
    case IBUS_KEY_Alt_R:
Packit 3ff832
    // Chrome OS does not have Meta key. Instead, shift+alt generates Meta keyval.
Packit 3ff832
    case IBUS_KEY_Meta_L:
Packit 3ff832
    case IBUS_KEY_Meta_R:
Packit 3ff832
        return modifiers | IBUS_MOD1_MASK;
Packit 3ff832
    case IBUS_KEY_Super_L:
Packit 3ff832
    case IBUS_KEY_Super_R:
Packit 3ff832
        return modifiers | IBUS_SUPER_MASK;
Packit 3ff832
    case IBUS_KEY_Hyper_L:
Packit 3ff832
    case IBUS_KEY_Hyper_R:
Packit 3ff832
        return modifiers | IBUS_HYPER_MASK;
Packit 3ff832
    default:
Packit 3ff832
        return modifiers;
Packit 3ff832
    }
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static gboolean
Packit 3ff832
is_modifier (guint keyval)
Packit 3ff832
{
Packit 3ff832
    switch(keyval) {
Packit 3ff832
    case IBUS_KEY_Control_L:
Packit 3ff832
    case IBUS_KEY_Control_R:
Packit 3ff832
    case IBUS_KEY_Shift_L:
Packit 3ff832
    case IBUS_KEY_Shift_R:
Packit 3ff832
    case IBUS_KEY_Alt_L:
Packit 3ff832
    case IBUS_KEY_Alt_R:
Packit 3ff832
    case IBUS_KEY_Meta_L:
Packit 3ff832
    case IBUS_KEY_Meta_R:
Packit 3ff832
    case IBUS_KEY_Super_L:
Packit 3ff832
    case IBUS_KEY_Super_R:
Packit 3ff832
    case IBUS_KEY_Hyper_L:
Packit 3ff832
    case IBUS_KEY_Hyper_R:
Packit 3ff832
        return TRUE;
Packit 3ff832
    default:
Packit 3ff832
        return FALSE;
Packit 3ff832
    }
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
gboolean
Packit 3ff832
ibus_hotkey_profile_add_hotkey (IBusHotkeyProfile *profile,
Packit 3ff832
                                guint              keyval,
Packit 3ff832
                                guint              modifiers,
Packit 3ff832
                                GQuark             event)
Packit 3ff832
{
Packit 3ff832
    IBusHotkeyProfilePrivate *priv;
Packit 3ff832
    priv = IBUS_HOTKEY_PROFILE_GET_PRIVATE (profile);
Packit 3ff832
Packit 3ff832
    IBusHotkey *hotkey = ibus_hotkey_new (keyval,
Packit 3ff832
                                          normalize_modifiers (keyval, modifiers & priv->mask));
Packit 3ff832
Packit 3ff832
    /* has the same hotkey in profile */
Packit 3ff832
    if (g_tree_lookup (priv->hotkeys, hotkey) != NULL) {
Packit 3ff832
        ibus_hotkey_free (hotkey);
Packit 3ff832
        g_return_val_if_reached (FALSE);
Packit 3ff832
    }
Packit 3ff832
Packit 3ff832
    g_tree_insert (priv->hotkeys, (gpointer) hotkey, GUINT_TO_POINTER (event));
Packit 3ff832
Packit 3ff832
    IBusHotkeyEvent *p = NULL;
Packit 3ff832
    gint i;
Packit 3ff832
    for ( i = 0; i < priv->events->len; i++) {
Packit 3ff832
        p = &g_array_index (priv->events, IBusHotkeyEvent, i);
Packit 3ff832
        if (p->event == event)
Packit 3ff832
            break;
Packit 3ff832
    }
Packit 3ff832
Packit 3ff832
    if (i >= priv->events->len) {
Packit 3ff832
        g_array_set_size (priv->events, i + 1);
Packit 3ff832
        p = &g_array_index (priv->events, IBusHotkeyEvent, i);
Packit 3ff832
        p->event = event;
Packit 3ff832
    }
Packit 3ff832
Packit 3ff832
    p->hotkeys = g_list_append (p->hotkeys, hotkey);
Packit 3ff832
Packit 3ff832
    return TRUE;
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
Packit 3ff832
gboolean
Packit 3ff832
ibus_hotkey_profile_add_hotkey_from_string (IBusHotkeyProfile *profile,
Packit 3ff832
                                            const gchar       *str,
Packit 3ff832
                                            GQuark             event)
Packit 3ff832
{
Packit 3ff832
    guint keyval;
Packit 3ff832
    guint modifiers;
Packit 3ff832
Packit 3ff832
    if (ibus_key_event_from_string (str, &keyval, &modifiers) == FALSE) {
Packit 3ff832
        return FALSE;
Packit 3ff832
    }
Packit 3ff832
Packit 3ff832
    return ibus_hotkey_profile_add_hotkey (profile, keyval, modifiers, event);
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
gboolean
Packit 3ff832
ibus_hotkey_profile_remove_hotkey (IBusHotkeyProfile *profile,
Packit 3ff832
                                   guint              keyval,
Packit 3ff832
                                   guint              modifiers)
Packit 3ff832
{
Packit 3ff832
    IBusHotkeyProfilePrivate *priv;
Packit 3ff832
    priv = IBUS_HOTKEY_PROFILE_GET_PRIVATE (profile);
Packit 3ff832
Packit 3ff832
    modifiers = normalize_modifiers (keyval, modifiers & priv->mask);
Packit 3ff832
Packit 3ff832
    IBusHotkey hotkey = {
Packit 3ff832
        .keyval = keyval,
Packit 3ff832
        .modifiers = modifiers
Packit 3ff832
    };
Packit 3ff832
Packit 3ff832
    IBusHotkey *p1;
Packit 3ff832
    GQuark event;
Packit 3ff832
    gboolean retval;
Packit 3ff832
Packit 3ff832
    retval = g_tree_lookup_extended (priv->hotkeys,
Packit 3ff832
                                     &hotkey,
Packit 3ff832
                                     (gpointer)&p1,
Packit 3ff832
                                     (gpointer)&event);
Packit 3ff832
Packit 3ff832
    if (!retval)
Packit 3ff832
        return FALSE;
Packit 3ff832
Packit 3ff832
    gint i;
Packit 3ff832
    IBusHotkeyEvent *p2 = NULL;
Packit 3ff832
    for ( i = 0; i < priv->events->len; i++) {
Packit 3ff832
        p2 = &g_array_index (priv->events, IBusHotkeyEvent, i);
Packit 3ff832
        if (p2->event == event)
Packit 3ff832
            break;
Packit 3ff832
    }
Packit 3ff832
Packit 3ff832
    g_assert (p2 && p2->event == event);
Packit 3ff832
Packit 3ff832
    p2->hotkeys = g_list_remove (p2->hotkeys, p1);
Packit 3ff832
    if (p2->hotkeys == NULL) {
Packit 3ff832
        g_array_remove_index_fast (priv->events, i);
Packit 3ff832
    }
Packit 3ff832
Packit 3ff832
    g_tree_remove (priv->hotkeys, p1);
Packit 3ff832
Packit 3ff832
    return TRUE;
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
gboolean
Packit 3ff832
ibus_hotkey_profile_remove_hotkey_by_event (IBusHotkeyProfile *profile,
Packit 3ff832
                                            GQuark             event)
Packit 3ff832
{
Packit 3ff832
    IBusHotkeyProfilePrivate *priv;
Packit 3ff832
    priv = IBUS_HOTKEY_PROFILE_GET_PRIVATE (profile);
Packit 3ff832
Packit 3ff832
    gint i;
Packit 3ff832
    IBusHotkeyEvent *p = NULL;
Packit 3ff832
    for ( i = 0; i < priv->events->len; i++) {
Packit 3ff832
        p = &g_array_index (priv->events, IBusHotkeyEvent, i);
Packit 3ff832
        if (p->event == event)
Packit 3ff832
            break;
Packit 3ff832
    }
Packit 3ff832
Packit 3ff832
    if (p == NULL || p->event != event)
Packit 3ff832
        return FALSE;
Packit 3ff832
Packit 3ff832
    GList *list;
Packit 3ff832
    for (list = p->hotkeys; list != NULL; list = list->next) {
Packit 3ff832
        g_tree_remove (priv->hotkeys, (IBusHotkey *)list->data);
Packit 3ff832
    }
Packit 3ff832
Packit 3ff832
    g_list_free (p->hotkeys);
Packit 3ff832
    g_array_remove_index_fast (priv->events, i);
Packit 3ff832
Packit 3ff832
    return TRUE;
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
GQuark
Packit 3ff832
ibus_hotkey_profile_filter_key_event (IBusHotkeyProfile *profile,
Packit 3ff832
                                      guint              keyval,
Packit 3ff832
                                      guint              modifiers,
Packit 3ff832
                                      guint              prev_keyval,
Packit 3ff832
                                      guint              prev_modifiers,
Packit 3ff832
                                      gpointer           user_data)
Packit 3ff832
{
Packit 3ff832
    IBusHotkeyProfilePrivate *priv;
Packit 3ff832
    priv = IBUS_HOTKEY_PROFILE_GET_PRIVATE (profile);
Packit 3ff832
Packit 3ff832
    modifiers = normalize_modifiers (keyval, modifiers & priv->mask);
Packit 3ff832
    prev_modifiers = normalize_modifiers (prev_keyval, prev_modifiers & priv->mask);
Packit 3ff832
Packit 3ff832
    IBusHotkey hotkey = {
Packit 3ff832
        .keyval = keyval,
Packit 3ff832
        .modifiers = modifiers,
Packit 3ff832
    };
Packit 3ff832
Packit 3ff832
    if (modifiers & IBUS_RELEASE_MASK) {
Packit 3ff832
        /* previous key event must be a press key event */
Packit 3ff832
        if (prev_modifiers & IBUS_RELEASE_MASK)
Packit 3ff832
            return 0;
Packit 3ff832
Packit 3ff832
        /* modifiers should be same except the release bit */
Packit 3ff832
        if (modifiers != (prev_modifiers | IBUS_RELEASE_MASK))
Packit 3ff832
            return 0;
Packit 3ff832
Packit 3ff832
        /* If it is release key event,
Packit 3ff832
         * we need check if keyval is equal to the prev keyval.
Packit 3ff832
         * If keyval is not equal to the prev keyval,
Packit 3ff832
         * but both keyvals are modifier keys,
Packit 3ff832
         * we will still search it in hotkeys.
Packit 3ff832
         * It is for matching some key sequences like:
Packit 3ff832
         * Shift Down, Alt Down, Shift Up => Shift+Alt+Release - Shift hotkey
Packit 3ff832
         **/
Packit 3ff832
        if ((keyval != prev_keyval) &&
Packit 3ff832
            (is_modifier (keyval) == FALSE ||
Packit 3ff832
             is_modifier (prev_keyval) == FALSE))
Packit 3ff832
            return 0;
Packit 3ff832
    }
Packit 3ff832
Packit 3ff832
    GQuark event = (GQuark) GPOINTER_TO_UINT (g_tree_lookup (priv->hotkeys, &hotkey));
Packit 3ff832
Packit 3ff832
    if (event != 0) {
Packit 3ff832
        g_signal_emit (profile, profile_signals[TRIGGER], event, user_data);
Packit 3ff832
    }
Packit 3ff832
Packit 3ff832
    return event;
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
GQuark
Packit 3ff832
ibus_hotkey_profile_lookup_hotkey (IBusHotkeyProfile *profile,
Packit 3ff832
                                   guint              keyval,
Packit 3ff832
                                   guint              modifiers)
Packit 3ff832
{
Packit 3ff832
    IBusHotkeyProfilePrivate *priv;
Packit 3ff832
    priv = IBUS_HOTKEY_PROFILE_GET_PRIVATE (profile);
Packit 3ff832
Packit 3ff832
    modifiers = normalize_modifiers (keyval, modifiers & priv->mask);
Packit 3ff832
Packit 3ff832
    IBusHotkey hotkey = {
Packit 3ff832
        .keyval = keyval,
Packit 3ff832
        .modifiers = modifiers,
Packit 3ff832
    };
Packit 3ff832
Packit 3ff832
    return (GQuark) GPOINTER_TO_UINT (g_tree_lookup (priv->hotkeys, &hotkey));
Packit 3ff832
}