This commit is contained in:
Tokuhiro Matsuno
2023-01-12 21:47:15 +09:00
parent e3887baacf
commit e970daf54a
7 changed files with 119 additions and 50 deletions

View File

@ -2,7 +2,7 @@ use std::collections::HashMap;
use ibus_sys::engine::IBusEngine;
use crate::context::InputMode;
use crate::input_mode::{INPUT_MODE_ALNUM, INPUT_MODE_HIRAGANA};
use crate::AkazaContext;
/**
@ -25,10 +25,10 @@ pub(crate) fn ibus_akaza_commands_map() -> HashMap<&'static str, IbusAkazaComman
context.commit_string(engine, surface.as_str());
});
register("set_input_mode_hiragana", |context, engine| {
context.set_input_mode(InputMode::Hiragana, engine)
context.set_input_mode(engine, &INPUT_MODE_HIRAGANA)
});
register("set_input_mode_alnum", |context, engine| {
context.set_input_mode(InputMode::Alnum, engine)
context.set_input_mode(engine, &INPUT_MODE_ALNUM)
});
register("update_candidates", |context, engine| {
context.update_candidates(engine)

View File

@ -4,7 +4,7 @@ use std::ops::Range;
use anyhow::Result;
use kelp::{h2z, hira2kata, z2h, ConvOption};
use log::{error, info, trace, warn};
use log::{debug, error, info, trace, warn};
use ibus_sys::attr_list::{ibus_attr_list_append, ibus_attr_list_new};
use ibus_sys::attribute::{
@ -29,8 +29,9 @@ use ibus_sys::glib::{gboolean, guint};
use ibus_sys::lookup_table::IBusLookupTable;
use ibus_sys::prop_list::{ibus_prop_list_append, ibus_prop_list_new, IBusPropList};
use ibus_sys::property::{
ibus_property_new, ibus_property_set_sub_props, IBusPropState_PROP_STATE_UNCHECKED,
IBusPropType_PROP_TYPE_MENU, IBusPropType_PROP_TYPE_RADIO, IBusProperty,
ibus_property_new, ibus_property_set_sub_props, IBusPropState_PROP_STATE_CHECKED,
IBusPropState_PROP_STATE_UNCHECKED, IBusPropType_PROP_TYPE_MENU, IBusPropType_PROP_TYPE_RADIO,
IBusProperty,
};
use ibus_sys::text::{ibus_text_new_from_string, ibus_text_set_attributes, IBusText, StringExt};
use libakaza::engine::base::HenkanEngine;
@ -40,15 +41,17 @@ use libakaza::graph::graph_resolver::Candidate;
use libakaza::romkan::RomKanConverter;
use crate::commands::{ibus_akaza_commands_map, IbusAkazaCommand};
use crate::input_mode::get_all_input_modes;
use crate::input_mode::{
get_all_input_modes, get_input_mode_from_prop_name, InputMode, INPUT_MODE_HIRAGANA,
};
use crate::keymap::KeyMap;
#[repr(C)]
#[derive(Debug)]
pub(crate) enum InputMode {
Hiragana,
Alnum,
}
// #[repr(C)]
// #[derive(Debug)]
// pub(crate) enum InputMode {
// Hiragana,
// Alnum,
// }
#[derive(Debug, Hash, PartialEq, Copy, Clone)]
pub enum KeyState {
@ -84,6 +87,34 @@ pub struct AkazaContext {
pub prop_dict: HashMap<String, *mut IBusProperty>,
}
impl AkazaContext {
/// Set props
pub(crate) fn do_property_activate(
&mut self,
engine: *mut IBusEngine,
prop_name: String,
prop_state: guint,
) {
debug!("do_property_activate: {}, {}", prop_name, prop_state);
if prop_state == IBusPropState_PROP_STATE_CHECKED && prop_name.starts_with("InputMode.") {
self.input_mode_activate(engine, prop_name, prop_state);
}
}
pub fn input_mode_activate(
&mut self,
engine: *mut IBusEngine,
prop_name: String,
_prop_state: guint,
) {
if let Ok(input_mode) = get_input_mode_from_prop_name(prop_name.as_str()) {
self.set_input_mode(engine, &input_mode);
} else {
warn!("Unknown prop_name: {}", prop_name);
}
}
}
impl AkazaContext {
pub(crate) fn process_num_key(&mut self, nn: i32, engine: *mut IBusEngine) {
let idx = if nn == 0 { 9 } else { nn - 1 };
@ -131,7 +162,7 @@ impl AkazaContext {
pub(crate) fn new(akaza: BigramWordViterbiEngine) -> Self {
let (input_mode_prop, prop_list, prop_dict) = Self::init_props();
AkazaContext {
input_mode: InputMode::Hiragana,
input_mode: INPUT_MODE_HIRAGANA,
cursor_pos: 0,
preedit: String::new(),
// self.lookup_table = IBus.LookupTable.new(page_size=10, cursor_pos=0, cursor_visible=True, round=True)
@ -175,7 +206,7 @@ impl AkazaContext {
) as gpointer) as *mut IBusProperty;
ibus_prop_list_append(prop_list, input_mode_prop);
let props = ibus_prop_list_new();
let props = g_object_ref_sink(ibus_prop_list_new() as gpointer) as *mut IBusPropList;
let mut prop_map: HashMap<String, *mut IBusProperty> = HashMap::new();
for input_mode in get_all_input_modes() {
let prop = g_object_ref_sink(ibus_property_new(
@ -245,8 +276,8 @@ impl AkazaContext {
return self.run_callback_by_name(engine, callback.as_str());
}
match &self.input_mode {
InputMode::Hiragana => {
match self.input_mode.prop_name {
"InputMode.Hiragana" => {
if modifiers
& (IBusModifierType_IBUS_CONTROL_MASK | IBusModifierType_IBUS_MOD1_MASK)
!= 0
@ -270,8 +301,11 @@ impl AkazaContext {
return true;
}
}
InputMode::Alnum => return false,
// _ => return false,
"InputMode.Alphanumeric" => return false,
_ => {
warn!("Unknown prop: {}", self.input_mode.prop_name);
return false;
}
}
false // not proceeded
@ -356,7 +390,7 @@ impl AkazaContext {
/**
* 入力モードの変更
*/
pub(crate) fn set_input_mode(&mut self, input_mode: InputMode, engine: *mut IBusEngine) {
pub(crate) fn set_input_mode(&mut self, engine: *mut IBusEngine, input_mode: &InputMode) {
info!("Changing input mode to : {:?}", input_mode);
// 変換候補をいったんコミットする。
@ -364,29 +398,18 @@ impl AkazaContext {
// TODO update menu prop
self.input_mode = input_mode;
/*
def _set_input_mode(self, mode: InputMode):
"""
label = _("Input mode (%s)") % mode.symbol
prop = self.input_mode_prop
prop.set_symbol(IBus.Text.new_from_string(mode.symbol))
prop.set_label(IBus.Text.new_from_string(label))
self.update_property(prop)
"""
self.logger.info(f"input mode activate: {mode}")
self.__prop_dict[mode.prop_name].set_state(IBus.PropState.CHECKED)
self.update_property(self.__prop_dict[mode.prop_name])
*/
# 変換候補をいったんコミットする。
self.commit_candidate()
label = _("Input mode (%s)") % mode.symbol
prop = self.input_mode_prop
prop.set_symbol(IBus.Text.new_from_string(mode.symbol))
prop.set_label(IBus.Text.new_from_string(label))
self.update_property(prop)
self.__prop_dict[mode.prop_name].set_state(IBus.PropState.CHECKED)
self.update_property(self.__prop_dict[mode.prop_name])
self.input_mode = mode
*/
self.input_mode = input_mode.clone();
}
pub(crate) fn run_callback_by_name(

View File

@ -1,5 +1,6 @@
use anyhow::bail;
#[derive(Copy, Clone, Debug)]
pub struct InputMode {
pub prop_name: &'static str,
pub mode_code: i32,
@ -29,19 +30,19 @@ impl InputMode {
}
}
const INPUT_MODE_ALNUM: InputMode =
pub const INPUT_MODE_ALNUM: InputMode =
InputMode::new("InputMode.Alphanumeric", 0, "_A", "Alphanumeric (C-S-;)");
const INPUT_MODE_HIRAGANA: InputMode =
pub const INPUT_MODE_HIRAGANA: InputMode =
InputMode::new("InputMode.Hiragana", 1, "", "Hiragana (C-S-j)");
const INPUT_MODE_KATAKANA: InputMode =
pub const INPUT_MODE_KATAKANA: InputMode =
InputMode::new("InputMode.Katakana", 2, "", "Katakana (C-S-K)");
const INPUT_MODE_HALFWIDTH_KATAKANA: InputMode = InputMode::new(
pub const INPUT_MODE_HALFWIDTH_KATAKANA: InputMode = InputMode::new(
"InputMode.HalfWidthKatakana",
3,
"_ア",
"Half-width Katakana",
);
const INPUT_MODE_FULLWIDTH_ALNUM: InputMode = InputMode::new(
pub const INPUT_MODE_FULLWIDTH_ALNUM: InputMode = InputMode::new(
"InputMode.FullWidthAlnum",
4,
"",

View File

@ -1,6 +1,8 @@
#![allow(non_upper_case_globals)]
use std::ffi::c_void;
extern crate alloc;
use std::ffi::{c_char, c_void, CStr};
use std::sync::{Arc, Mutex};
use std::time::SystemTime;
use std::{thread, time};
@ -11,7 +13,7 @@ use log::{error, info, warn};
use ibus_sys::core::ibus_main;
use ibus_sys::engine::IBusEngine;
use ibus_sys::glib::guint;
use ibus_sys::glib::{gchar, guint};
use libakaza::engine::bigram_word_viterbi_engine::BigramWordViterbiEngineBuilder;
use libakaza::user_side_data::user_data::UserData;
@ -51,6 +53,22 @@ unsafe extern "C" fn focus_in(context: *mut c_void, engine: *mut IBusEngine) {
context_ref.do_focus_in(engine);
}
unsafe extern "C" fn property_activate(
context: *mut c_void,
engine: *mut IBusEngine,
prop_name: *mut gchar,
prop_state: guint,
) {
let context_ref = &mut *(context as *mut AkazaContext);
context_ref.do_property_activate(
engine,
CStr::from_ptr(prop_name as *mut c_char)
.to_string_lossy()
.to_string(),
prop_state,
);
}
fn load_user_data() -> Arc<Mutex<UserData>> {
match UserData::load_from_default_path() {
Ok(user_data) => Arc::new(Mutex::new(user_data)),
@ -118,6 +136,7 @@ fn main() -> Result<()> {
process_key_event,
candidate_clicked,
focus_in,
property_activate,
);
ibus_akaza_init(arg.ibus);

View File

@ -5,7 +5,7 @@
use std::ffi::c_void;
use ibus_sys::engine::IBusEngine;
use ibus_sys::glib::guint;
use ibus_sys::glib::{gchar, guint};
// FFI for the wrapper.c
pub(crate) type ibus_akaza_callback_key_event = unsafe extern "C" fn(
@ -24,6 +24,13 @@ pub(crate) type ibus_akaza_callback_candidate_clicked = unsafe extern "C" fn(
state: guint,
);
pub(crate) type ibus_akaza_callback_property_activate = unsafe extern "C" fn(
context: *mut c_void,
engine: *mut IBusEngine,
prop_name: *mut gchar,
prop_state: guint,
);
pub(crate) type ibus_akaza_callback_focus_in =
unsafe extern "C" fn(context: *mut c_void, engine: *mut IBusEngine);
@ -36,5 +43,6 @@ extern "C" {
key_event_cb: ibus_akaza_callback_key_event,
candidate_cb: ibus_akaza_callback_candidate_clicked,
focus_in_cb: ibus_akaza_callback_focus_in,
property_activate: ibus_akaza_callback_property_activate,
);
}

View File

@ -10,6 +10,7 @@ static void* global_context = NULL;
static ibus_akaza_callback_key_event global_key_event_cb = NULL;
static ibus_akaza_callback_candidate_clicked global_candidate_clicked_cb = NULL;
static ibus_akaza_callback_focus_in global_focus_in_cb = NULL;
static ibus_akaza_callback_property_activate global_property_activate_cb = NULL;
#define IBUS_TYPE_AKAZA_ENGINE \
(ibus_akaza_engine_get_type ())
@ -31,6 +32,11 @@ static gboolean ibus_akaza_engine_process_key_event(IBusEngine *engine,
static void ibus_akaza_engine_focus_in(
IBusEngine *engine
);
static void ibus_akaza_engine_property_activate(
IBusEngine *engine,
const gchar *prop_name,
guint prop_state
);
G_DEFINE_TYPE(IBusAkazaEngine, ibus_akaza_engine, IBUS_TYPE_ENGINE)
@ -57,6 +63,14 @@ static void ibus_akaza_engine_focus_in(
global_focus_in_cb(global_context, engine);
}
static void ibus_akaza_engine_property_activate(
IBusEngine *engine,
const gchar *prop_name,
guint prop_state
) {
global_property_activate_cb(global_context, engine, prop_name, prop_state);
}
static gboolean ibus_akaza_engine_process_key_event(IBusEngine *engine,
guint keyval,
guint keycode,
@ -78,6 +92,7 @@ static void ibus_akaza_engine_class_init(IBusAkazaEngineClass *klass) {
engine_class->process_key_event = ibus_akaza_engine_process_key_event;
engine_class->candidate_clicked = ibus_akaza_engine_candidate_clicked;
engine_class->focus_in = ibus_akaza_engine_focus_in;
engine_class->property_activate = ibus_akaza_engine_property_activate;
}
@ -85,12 +100,14 @@ void ibus_akaza_set_callback(
void* context,
ibus_akaza_callback_key_event* key_event_cb,
ibus_akaza_callback_candidate_clicked* candidate_cb,
ibus_akaza_callback_focus_in* focus_in_cb
ibus_akaza_callback_focus_in* focus_in_cb,
ibus_akaza_callback_property_activate* property_activate_cb
) {
global_context = context;
global_key_event_cb = key_event_cb;
global_candidate_clicked_cb = candidate_cb;
global_focus_in_cb = focus_in_cb;
global_property_activate_cb = property_activate_cb;
}
void ibus_akaza_init(bool ibus) {

View File

@ -5,8 +5,9 @@
typedef gboolean (*ibus_akaza_callback_key_event)(void* ctx, IBusEngine* engine, guint keyval, guint keycode, guint modifiers);
typedef gboolean (*ibus_akaza_callback_candidate_clicked)(void* ctx, IBusEngine* engine, guint index, guint button, guint state);
typedef void (*ibus_akaza_callback_focus_in)(void* ctx, IBusEngine* engine);
typedef void (*ibus_akaza_callback_property_activate)(void* ctx, IBusEngine* engine, const gchar *prop_name, guint prop_state);
void ibus_akaza_set_callback(void* ctx, ibus_akaza_callback_key_event* cb, ibus_akaza_callback_candidate_clicked*, ibus_akaza_callback_focus_in*);
void ibus_akaza_set_callback(void* ctx, ibus_akaza_callback_key_event* cb, ibus_akaza_callback_candidate_clicked*, ibus_akaza_callback_focus_in*, ibus_akaza_callback_property_activate*);
typedef struct {
IBusEngine parent;