mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-05 00:15:32 +00:00
chore(linux): Implement Linux side of caps-lock action processing
This commit is contained in:
parent
dabfea57ab
commit
cfeb9e820e
3 changed files with 157 additions and 115 deletions
|
|
@ -58,6 +58,11 @@ PKG_CHECK_MODULES(GTK, [
|
|||
gtk+-3.0 >= 2.4
|
||||
])
|
||||
|
||||
# Check X11
|
||||
PKG_CHECK_MODULES(X11, [
|
||||
x11 >= 1.6
|
||||
])
|
||||
|
||||
# check atkspi 2.0
|
||||
#PKG_CHECK_MODULES(ATSPI, [
|
||||
# atspi-2 >= 2.0
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ AM_CFLAGS = \
|
|||
@IBUS_CFLAGS@ \
|
||||
@GTK_CFLAGS@ \
|
||||
@JSON_GLIB_CFLAGS@ \
|
||||
@X11_CFLAGS@ \
|
||||
@KEYMAN_PROC_CFLAGS@ \
|
||||
-DPKGDATADIR=\"$(pkgdatadir)\" \
|
||||
$(NULL)
|
||||
|
|
@ -29,6 +30,7 @@ AM_CFLAGS = \
|
|||
AM_LDFLAGS = \
|
||||
@IBUS_LIBS@ \
|
||||
@GTK_LIBS@ \
|
||||
@X11_LIBS@ \
|
||||
@JSON_GLIB_LIBS@ \
|
||||
@KEYMAN_PROC_LIBS@ \
|
||||
$(NULL)
|
||||
|
|
@ -73,6 +75,7 @@ ibus_engine_keyman_SOURCES = \
|
|||
ibus_engine_keyman_CFLAGS = \
|
||||
@IBUS_CFLAGS@ \
|
||||
@GTK_CFLAGS@ \
|
||||
@X11_CFLAGS@ \
|
||||
@JSON_GLIB_CFLAGS@ \
|
||||
@KEYMAN_PROC_CFLAGS@ \
|
||||
-DPKGDATADIR=\"$(pkgdatadir)\" \
|
||||
|
|
@ -81,6 +84,7 @@ ibus_engine_keyman_CFLAGS = \
|
|||
ibus_engine_keyman_LDFLAGS = \
|
||||
@GTK_LIBS@ \
|
||||
@IBUS_LIBS@ \
|
||||
@X11_LIBS@ \
|
||||
@JSON_GLIB_LIBS@ \
|
||||
@KEYMAN_PROC_LIBS@ \
|
||||
$(NULL)
|
||||
|
|
|
|||
|
|
@ -27,6 +27,12 @@
|
|||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
#include <gdk/gdkx.h>
|
||||
#include <X11/XKBlib.h>
|
||||
#endif
|
||||
|
||||
#include <keyman/keyboardprocessor.h>
|
||||
|
||||
#include "keymanutil.h"
|
||||
|
|
@ -41,6 +47,7 @@
|
|||
#define KEYMAN_RCTRL 97
|
||||
#define KEYMAN_RALT 100
|
||||
#define KEYMAN_CAPS 0x3a
|
||||
#define KEYMAN_CAPS_KEYSYM IBUS_KEY_Caps_Lock
|
||||
|
||||
typedef struct _IBusKeymanEngine IBusKeymanEngine;
|
||||
typedef struct _IBusKeymanEngineClass IBusKeymanEngineClass;
|
||||
|
|
@ -63,6 +70,9 @@ struct _IBusKeymanEngine {
|
|||
IBusLookupTable *table;
|
||||
IBusProperty *status_prop;
|
||||
IBusPropList *prop_list;
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
Display *xdisplay;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _IBusKeymanEngineClass {
|
||||
|
|
@ -238,32 +248,34 @@ static void reset_context(IBusEngine *engine)
|
|||
}
|
||||
|
||||
static void
|
||||
ibus_keyman_engine_init (IBusKeymanEngine *keyman)
|
||||
{
|
||||
keyman->status_prop = ibus_property_new ("status",
|
||||
PROP_TYPE_NORMAL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
TRUE,
|
||||
FALSE,
|
||||
0,
|
||||
NULL);
|
||||
g_object_ref_sink(keyman->status_prop);
|
||||
keyman->prop_list = ibus_prop_list_new ();
|
||||
g_object_ref_sink(keyman->prop_list);
|
||||
ibus_prop_list_append (keyman->prop_list, keyman->status_prop);
|
||||
ibus_keyman_engine_init(IBusKeymanEngine *keyman) {
|
||||
gdk_init(NULL, NULL);
|
||||
keyman->status_prop = ibus_property_new("status", PROP_TYPE_NORMAL, NULL, NULL, NULL, TRUE, FALSE, 0, NULL);
|
||||
g_object_ref_sink(keyman->status_prop);
|
||||
keyman->prop_list = ibus_prop_list_new();
|
||||
g_object_ref_sink(keyman->prop_list);
|
||||
ibus_prop_list_append(keyman->prop_list, keyman->status_prop);
|
||||
|
||||
keyman->table = ibus_lookup_table_new (9, 0, TRUE, TRUE);
|
||||
g_object_ref_sink(keyman->table);
|
||||
keyman->state = NULL;
|
||||
keyman->table = ibus_lookup_table_new(9, 0, TRUE, TRUE);
|
||||
g_object_ref_sink(keyman->table);
|
||||
keyman->state = NULL;
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
keyman->xdisplay = NULL;
|
||||
if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
|
||||
keyman->xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
g_error("unsupported GDK backend");
|
||||
}
|
||||
}
|
||||
|
||||
static GObject*
|
||||
ibus_keyman_engine_constructor (GType type,
|
||||
guint n_construct_params,
|
||||
GObjectConstructParam *construct_params)
|
||||
{
|
||||
ibus_keyman_engine_constructor(
|
||||
GType type,
|
||||
guint n_construct_params,
|
||||
GObjectConstructParam *construct_params
|
||||
) {
|
||||
IBusKeymanEngine *keyman;
|
||||
IBusEngine *engine;
|
||||
IBusText *text;
|
||||
|
|
@ -584,7 +596,8 @@ static gboolean ok_for_single_backspace(const km_kbp_action_item *action_items,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean process_unicode_char_action(
|
||||
static gboolean
|
||||
process_unicode_char_action(
|
||||
IBusKeymanEngine *keyman,
|
||||
const km_kbp_action_item *action_item
|
||||
) {
|
||||
|
|
@ -691,7 +704,8 @@ process_backspace_action(
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean process_persist_action(
|
||||
static gboolean
|
||||
process_persist_action(
|
||||
IBusKeymanEngine *keyman,
|
||||
const km_kbp_action_item *action_item
|
||||
) {
|
||||
|
|
@ -735,6 +749,23 @@ static gboolean process_invalidate_context_action(IBusEngine *engine) {
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
process_capslock_action(
|
||||
IBusKeymanEngine *keyman,
|
||||
const km_kbp_action_item *action_item
|
||||
) {
|
||||
g_message("**** %s caps-lock", action_item->capsLock ? "Enable" : "Disable");
|
||||
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
if (keyman->xdisplay) {
|
||||
XkbLockModifiers(keyman->xdisplay, XkbUseCoreKbd, LockMask, action_item->capsLock ? LockMask : 0);
|
||||
|
||||
XSync(keyman->xdisplay, False);
|
||||
}
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean process_end_action(IBusKeymanEngine *keyman) {
|
||||
keyman->firstsurrogate = 0;
|
||||
if (keyman->char_buffer != NULL) {
|
||||
|
|
@ -750,7 +781,8 @@ static gboolean process_end_action(IBusKeymanEngine *keyman) {
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean process_actions(
|
||||
static gboolean
|
||||
process_actions(
|
||||
IBusEngine *engine,
|
||||
const km_kbp_action_item *action_items,
|
||||
size_t num_action_items
|
||||
|
|
@ -786,6 +818,10 @@ static gboolean process_actions(
|
|||
g_message("INVALIDATE_CONTEXT action %d/%d", i + 1, (int)num_action_items);
|
||||
continue_with_next_action = process_invalidate_context_action(engine);
|
||||
break;
|
||||
case KM_KBP_IT_CAPSLOCK:
|
||||
g_message("CAPSLOCK action %d/%d", i + 1, (int)num_action_items);
|
||||
continue_with_next_action = process_capslock_action(keyman, &action_items[i]);
|
||||
break;
|
||||
case KM_KBP_IT_END:
|
||||
g_message("END action %d/%d", i + 1, (int)num_action_items);
|
||||
continue_with_next_action = process_end_action(keyman);
|
||||
|
|
@ -800,103 +836,100 @@ static gboolean process_actions(
|
|||
}
|
||||
|
||||
static gboolean
|
||||
ibus_keyman_engine_process_key_event (IBusEngine *engine,
|
||||
guint keyval,
|
||||
guint keycode,
|
||||
guint state)
|
||||
{
|
||||
IBusKeymanEngine *keyman = (IBusKeymanEngine *) engine;
|
||||
ibus_keyman_engine_process_key_event(
|
||||
IBusEngine *engine,
|
||||
guint keyval,
|
||||
guint keycode,
|
||||
guint state
|
||||
) {
|
||||
IBusKeymanEngine *keyman = (IBusKeymanEngine *)engine;
|
||||
|
||||
g_message("DAR: ibus_keyman_engine_process_key_event - keyval=%02i, keycode=%02i, state=%02x", keyval, keycode, state);
|
||||
gboolean isKeyDown = !(state & IBUS_RELEASE_MASK);
|
||||
|
||||
gboolean isKeyDown = !!(state & IBUS_RELEASE_MASK);
|
||||
g_message("-----------------------------------------------------------------------------------------------------------------");
|
||||
g_message(
|
||||
"DAR: ibus_keyman_engine_process_key_event - keyval=0x%02x keycode=0x%02x, state=0x%02x, isKeyDown=%d", keyval, keycode,
|
||||
state, isKeyDown);
|
||||
|
||||
// REVIEW: why don't we handle these keys?
|
||||
switch (keycode) {
|
||||
case KEYMAN_LCTRL:
|
||||
keyman->lctrl_pressed = isKeyDown;
|
||||
break;
|
||||
case KEYMAN_RCTRL:
|
||||
keyman->rctrl_pressed = isKeyDown;
|
||||
break;
|
||||
case KEYMAN_LALT:
|
||||
keyman->lalt_pressed = isKeyDown;
|
||||
break;
|
||||
case KEYMAN_RALT:
|
||||
keyman->ralt_pressed = isKeyDown;
|
||||
break;
|
||||
// REVIEW: why don't we handle these keys?
|
||||
switch (keycode) {
|
||||
case KEYMAN_LCTRL:
|
||||
keyman->lctrl_pressed = isKeyDown;
|
||||
break;
|
||||
case KEYMAN_RCTRL:
|
||||
keyman->rctrl_pressed = isKeyDown;
|
||||
break;
|
||||
case KEYMAN_LALT:
|
||||
keyman->lalt_pressed = isKeyDown;
|
||||
break;
|
||||
case KEYMAN_RALT:
|
||||
keyman->ralt_pressed = isKeyDown;
|
||||
break;
|
||||
}
|
||||
|
||||
if (keycode < 0 || keycode > 255) {
|
||||
g_warning("keycode %d out of range", keycode);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (keycode_to_vk[keycode] == 0) { // key we don't handle
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// keyman modifiers are different from X11/ibus
|
||||
uint16_t km_mod_state = 0;
|
||||
if (state & IBUS_SHIFT_MASK) {
|
||||
km_mod_state |= KM_KBP_MODIFIER_SHIFT;
|
||||
}
|
||||
if (state & IBUS_MOD5_MASK) {
|
||||
km_mod_state |= KM_KBP_MODIFIER_RALT;
|
||||
g_message("modstate KM_KBP_MODIFIER_RALT from IBUS_MOD5_MASK");
|
||||
}
|
||||
if (state & IBUS_MOD1_MASK) {
|
||||
if (keyman->ralt_pressed) {
|
||||
km_mod_state |= KM_KBP_MODIFIER_RALT;
|
||||
g_message("modstate KM_KBP_MODIFIER_RALT from ralt_pressed");
|
||||
}
|
||||
if (keyman->lalt_pressed) {
|
||||
km_mod_state |= KM_KBP_MODIFIER_LALT;
|
||||
g_message("modstate KM_KBP_MODIFIER_LALT from lalt_pressed");
|
||||
}
|
||||
}
|
||||
if (state & IBUS_CONTROL_MASK) {
|
||||
if (keyman->rctrl_pressed) {
|
||||
km_mod_state |= KM_KBP_MODIFIER_RCTRL;
|
||||
g_message("modstate KM_KBP_MODIFIER_RCTRL from rctrl_pressed");
|
||||
}
|
||||
if (keyman->lctrl_pressed) {
|
||||
km_mod_state |= KM_KBP_MODIFIER_LCTRL;
|
||||
g_message("modstate KM_KBP_MODIFIER_LCTRL from lctrl_pressed");
|
||||
}
|
||||
}
|
||||
if (state & IBUS_LOCK_MASK) {
|
||||
km_mod_state |= KM_KBP_MODIFIER_CAPS;
|
||||
}
|
||||
g_message("before process key event");
|
||||
km_kbp_context *context = km_kbp_state_context(keyman->state);
|
||||
g_free(get_current_context_text(context));
|
||||
g_message("DAR: ibus_keyman_engine_process_key_event - km_mod_state=0x%x", km_mod_state);
|
||||
km_kbp_status event_status = km_kbp_process_event(keyman->state, keycode_to_vk[keycode], km_mod_state, isKeyDown);
|
||||
context = km_kbp_state_context(keyman->state);
|
||||
g_message("after process key event");
|
||||
g_free(get_current_context_text(context));
|
||||
|
||||
if (keycode < 0 || keycode > 255) {
|
||||
g_warning("keycode %d out of range", keycode);
|
||||
return FALSE;
|
||||
}
|
||||
// km_kbp_state_action_items to get action items
|
||||
size_t num_action_items;
|
||||
g_free(keyman->char_buffer);
|
||||
keyman->char_buffer = NULL;
|
||||
const km_kbp_action_item *action_items = km_kbp_state_action_items(keyman->state, &num_action_items);
|
||||
|
||||
if (keycode_to_vk[keycode] == 0) { // key we don't handle
|
||||
return FALSE;
|
||||
}
|
||||
if (!process_actions(engine, action_items, num_action_items))
|
||||
return FALSE;
|
||||
|
||||
// keyman modifiers are different from X11/ibus
|
||||
uint16_t km_mod_state = 0;
|
||||
if (state & IBUS_SHIFT_MASK)
|
||||
{
|
||||
km_mod_state |= KM_KBP_MODIFIER_SHIFT;
|
||||
}
|
||||
if (state & IBUS_MOD5_MASK)
|
||||
{
|
||||
km_mod_state |= KM_KBP_MODIFIER_RALT;
|
||||
g_message("modstate KM_KBP_MODIFIER_RALT from IBUS_MOD5_MASK");
|
||||
}
|
||||
if (state & IBUS_MOD1_MASK)
|
||||
{
|
||||
if (keyman->ralt_pressed) {
|
||||
km_mod_state |= KM_KBP_MODIFIER_RALT;
|
||||
g_message("modstate KM_KBP_MODIFIER_RALT from ralt_pressed");
|
||||
}
|
||||
if (keyman->lalt_pressed) {
|
||||
km_mod_state |= KM_KBP_MODIFIER_LALT;
|
||||
g_message("modstate KM_KBP_MODIFIER_LALT from lalt_pressed");
|
||||
}
|
||||
}
|
||||
if (state & IBUS_CONTROL_MASK)
|
||||
{
|
||||
if (keyman->rctrl_pressed) {
|
||||
km_mod_state |= KM_KBP_MODIFIER_RCTRL;
|
||||
g_message("modstate KM_KBP_MODIFIER_RCTRL from rctrl_pressed");
|
||||
}
|
||||
if (keyman->lctrl_pressed) {
|
||||
km_mod_state |= KM_KBP_MODIFIER_LCTRL;
|
||||
g_message("modstate KM_KBP_MODIFIER_LCTRL from lctrl_pressed");
|
||||
}
|
||||
}
|
||||
if (state & IBUS_LOCK_MASK)
|
||||
{
|
||||
km_mod_state |= KM_KBP_MODIFIER_CAPS;
|
||||
}
|
||||
g_message("before process key event");
|
||||
km_kbp_context *context = km_kbp_state_context(keyman->state);
|
||||
g_free(get_current_context_text(context));
|
||||
g_message("DAR: ibus_keyman_engine_process_key_event - km_mod_state=%x", km_mod_state);
|
||||
km_kbp_status event_status =
|
||||
km_kbp_process_event(keyman->state, keycode_to_vk[keycode], km_mod_state, isKeyDown);
|
||||
context = km_kbp_state_context(keyman->state);
|
||||
g_message("after process key event");
|
||||
g_free(get_current_context_text(context));
|
||||
|
||||
// km_kbp_state_action_items to get action items
|
||||
size_t num_action_items;
|
||||
g_free(keyman->char_buffer);
|
||||
keyman->char_buffer = NULL;
|
||||
const km_kbp_action_item *action_items = km_kbp_state_action_items(keyman->state,
|
||||
&num_action_items);
|
||||
|
||||
if (!process_actions(engine, action_items, num_action_items))
|
||||
return FALSE;
|
||||
|
||||
context = km_kbp_state_context(keyman->state);
|
||||
g_message("after processing all actions");
|
||||
g_free(get_current_context_text(context));
|
||||
return TRUE;
|
||||
context = km_kbp_state_context(keyman->state);
|
||||
g_message("after processing all actions");
|
||||
g_free(get_current_context_text(context));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue