forked from Qortal/Brooklyn
1421 lines
53 KiB
C++
1421 lines
53 KiB
C++
/*
|
|
SPDX-FileCopyrightText: 2011-2012 Ni Hui <shuizhuyuanluo@126.com>
|
|
SPDX-FileCopyrightText: 2013-2014 Weng Xuetian <wengxt@gmail.com>
|
|
|
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
|
*/
|
|
|
|
#include "panel.h"
|
|
#include "app.h"
|
|
#include "enginemanager.h"
|
|
#include "gtkaccelparse_p.h"
|
|
#include "propertymanager.h"
|
|
#include "xkblayoutmanager.h"
|
|
#include <QByteArray>
|
|
#include <QDebug>
|
|
#include <QPair>
|
|
#include <QStringList>
|
|
#include <locale.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <string>
|
|
|
|
#ifndef DBUS_ERROR_FAILED
|
|
#define DBUS_ERROR_FAILED "org.freedesktop.DBus.Error.Failed"
|
|
#endif /* DBUS_ERROR_FAILED */
|
|
|
|
#define IBUS_SCHEMA_GENERAL "org.freedesktop.ibus.general"
|
|
#define IBUS_SCHEMA_HOTKEY "org.freedesktop.ibus.general.hotkey"
|
|
#define IBUS_SCHEMA_PANEL "org.freedesktop.ibus.panel"
|
|
|
|
typedef struct _IBusPanelImpanelClass IBusPanelImpanelClass;
|
|
|
|
struct _IBusPanelImpanel {
|
|
IBusPanelService parent;
|
|
IBusBus *bus;
|
|
GDBusConnection *conn;
|
|
PropertyManager *propManager;
|
|
EngineManager *engineManager;
|
|
XkbLayoutManager *xkbLayoutManager;
|
|
App *app;
|
|
gboolean useSystemKeyboardLayout;
|
|
int selected;
|
|
GSettings *settings_general;
|
|
GSettings *settings_hotkey;
|
|
};
|
|
|
|
struct _IBusPanelImpanelClass {
|
|
IBusPanelServiceClass parent;
|
|
};
|
|
|
|
/* functions prototype */
|
|
static void ibus_panel_impanel_class_init(IBusPanelImpanelClass *klass);
|
|
static void ibus_panel_impanel_init(IBusPanelImpanel *impanel);
|
|
static void ibus_panel_impanel_destroy(IBusPanelImpanel *impanel);
|
|
|
|
static void ibus_panel_impanel_focus_in(IBusPanelService *panel, const gchar *input_context_path);
|
|
static void ibus_panel_impanel_focus_out(IBusPanelService *panel, const gchar *input_context_path);
|
|
static void ibus_panel_impanel_register_properties(IBusPanelService *panel, IBusPropList *prop_list);
|
|
static void ibus_panel_impanel_real_register_properties(IBusPanelImpanel *impanel);
|
|
static void ibus_panel_impanel_set_cursor_location(IBusPanelService *panel, gint x, gint y, gint w, gint h);
|
|
static void ibus_panel_impanel_update_auxiliary_text(IBusPanelService *panel, IBusText *text, gboolean visible);
|
|
static void ibus_panel_impanel_update_lookup_table(IBusPanelService *panel, IBusLookupTable *lookup_table, gboolean visible);
|
|
static void ibus_panel_impanel_update_preedit_text(IBusPanelService *panel, IBusText *text, guint cursor_pos, gboolean visible);
|
|
static void ibus_panel_impanel_update_property(IBusPanelService *panel, IBusProperty *prop);
|
|
static void ibus_panel_impanel_cursor_down_lookup_table(IBusPanelService *panel);
|
|
static void ibus_panel_impanel_cursor_up_lookup_table(IBusPanelService *panel);
|
|
static void ibus_panel_impanel_hide_auxiliary_text(IBusPanelService *panel);
|
|
static void ibus_panel_impanel_hide_language_bar(IBusPanelService *panel);
|
|
static void ibus_panel_impanel_hide_lookup_table(IBusPanelService *panel);
|
|
static void ibus_panel_impanel_hide_preedit_text(IBusPanelService *panel);
|
|
static void ibus_panel_impanel_page_down_lookup_table(IBusPanelService *panel);
|
|
static void ibus_panel_impanel_page_up_lookup_table(IBusPanelService *panel);
|
|
static void ibus_panel_impanel_reset(IBusPanelService *panel);
|
|
static void ibus_panel_impanel_show_auxiliary_text(IBusPanelService *panel);
|
|
static void ibus_panel_impanel_show_language_bar(IBusPanelService *panel);
|
|
static void ibus_panel_impanel_show_lookup_table(IBusPanelService *panel);
|
|
static void ibus_panel_impanel_show_preedit_text(IBusPanelService *panel);
|
|
static void ibus_panel_impanel_start_setup(IBusPanelService *panel);
|
|
static void ibus_panel_impanel_state_changed(IBusPanelService *panel);
|
|
|
|
/* impanel signal handler function */
|
|
static void ibus_panel_impanel_exec_im_menu(IBusPanelImpanel *impanel);
|
|
static void ibus_panel_impanel_exec_menu(IBusPanelImpanel *impanel, IBusPropList *prop_list);
|
|
|
|
static void impanel_set_engine(IBusPanelImpanel *impanel, const char *name);
|
|
|
|
static QByteArray ibus_property_to_propstr(IBusProperty *property, gboolean useSymbol = FALSE);
|
|
|
|
static QByteArray ibus_engine_desc_to_logo_propstr(IBusEngineDesc *engine);
|
|
|
|
void impanel_update_logo_by_engine(IBusPanelImpanel *impanel, IBusEngineDesc *engine_desc)
|
|
{
|
|
if (!impanel->conn) {
|
|
return;
|
|
}
|
|
|
|
QByteArray propstr = ibus_engine_desc_to_logo_propstr(engine_desc);
|
|
|
|
g_dbus_connection_emit_signal(impanel->conn,
|
|
nullptr,
|
|
"/kimpanel",
|
|
"org.kde.kimpanel.inputmethod",
|
|
"UpdateProperty",
|
|
(g_variant_new("(s)", propstr.constData())),
|
|
nullptr);
|
|
}
|
|
|
|
void ibus_panel_impanel_set_bus(IBusPanelImpanel *impanel, IBusBus *bus)
|
|
{
|
|
impanel->bus = bus;
|
|
}
|
|
|
|
void ibus_panel_impanel_set_app(IBusPanelImpanel *impanel, App *app)
|
|
{
|
|
impanel->app = app;
|
|
}
|
|
|
|
void ibus_panel_impanel_accept(IBusPanelImpanel *impanel)
|
|
{
|
|
if (impanel->selected >= 0 && static_cast<size_t>(impanel->selected) < impanel->engineManager->length()) {
|
|
impanel_set_engine(impanel, ibus_engine_desc_get_name(impanel->engineManager->engines()[impanel->selected]));
|
|
impanel->selected = -1;
|
|
}
|
|
}
|
|
|
|
void ibus_panel_impanel_navigate(IBusPanelImpanel *impanel, gboolean start, gboolean forward)
|
|
{
|
|
if (start) {
|
|
impanel->selected = -1;
|
|
}
|
|
|
|
if (impanel->engineManager->length() < 2) {
|
|
return;
|
|
}
|
|
|
|
IBusEngineDesc *engine_desc = nullptr;
|
|
if (impanel->selected < 0) {
|
|
engine_desc = ibus_bus_get_global_engine(impanel->bus);
|
|
} else if (static_cast<size_t>(impanel->selected) < impanel->engineManager->length()) {
|
|
engine_desc = impanel->engineManager->engines()[impanel->selected];
|
|
g_object_ref(engine_desc);
|
|
}
|
|
|
|
if (!engine_desc) {
|
|
engine_desc = impanel->engineManager->engines()[0];
|
|
g_object_ref(engine_desc);
|
|
}
|
|
|
|
if (engine_desc) {
|
|
const char *name = impanel->engineManager->navigate(engine_desc, forward);
|
|
impanel->selected = impanel->engineManager->getIndexByName(name);
|
|
g_object_unref(engine_desc);
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
if (impanel->selected >= 0 && static_cast<size_t>(impanel->selected) < impanel->engineManager->length()) {
|
|
ibus_panel_impanel_real_register_properties(impanel);
|
|
}
|
|
}
|
|
|
|
void ibus_panel_impanel_move_next(IBusPanelImpanel *impanel)
|
|
{
|
|
if (impanel->engineManager->length() >= 2) {
|
|
impanel_set_engine(impanel, ibus_engine_desc_get_name(impanel->engineManager->engines()[1]));
|
|
}
|
|
}
|
|
|
|
static GDBusNodeInfo *introspection_data = nullptr;
|
|
|
|
static guint owner_id;
|
|
|
|
static const gchar introspection_xml[] =
|
|
"<node>"
|
|
" <interface name='org.kde.kimpanel.inputmethod'>"
|
|
" <signal name='Enable'>"
|
|
" <arg type='b' name='enable'/>"
|
|
" </signal>"
|
|
" <signal name='RegisterProperties'>"
|
|
" <arg type='as' name='prop'/>"
|
|
" </signal>"
|
|
" <signal name='UpdateProperty'>"
|
|
" <arg type='s' name='prop'/>"
|
|
" </signal>"
|
|
" <signal name='RemoveProperty'>"
|
|
" <arg type='s' name='prop'/>"
|
|
" </signal>"
|
|
" <signal name='ShowAux'>"
|
|
" <arg type='b' name='toshow'/>"
|
|
" </signal>"
|
|
" <signal name='ShowLookupTable'>"
|
|
" <arg type='b' name='toshow'/>"
|
|
" </signal>"
|
|
" <signal name='ShowPreedit'>"
|
|
" <arg type='b' name='toshow'/>"
|
|
" </signal>"
|
|
" <signal name='UpdateAux'>"
|
|
" <arg type='s' name='text'/>"
|
|
" <arg type='s' name='attr'/>"
|
|
" </signal>"
|
|
" <signal name='UpdateLookupTableCursor'>"
|
|
" <arg type='i' name='pos'/>"
|
|
" </signal>"
|
|
" <signal name='UpdateLookupTable'>"
|
|
" <arg type='as' name='labels'/>"
|
|
" <arg type='as' name='candidates'/>"
|
|
" <arg type='as' name='attrs'/>"
|
|
" <arg type='b' name='hasprev'/>"
|
|
" <arg type='b' name='hasnext'/>"
|
|
" </signal>"
|
|
" <signal name='UpdatePreeditCaret'>"
|
|
" <arg type='i' name='pos'/>"
|
|
" </signal>"
|
|
" <signal name='UpdatePreeditText'>"
|
|
" <arg type='s' name='text'/>"
|
|
" <arg type='s' name='attr'/>"
|
|
" </signal>"
|
|
" <signal name='UpdateSpotLocation'>"
|
|
" <arg type='i' name='x'/>"
|
|
" <arg type='i' name='y'/>"
|
|
" </signal>"
|
|
" <signal name='ExecMenu'>"
|
|
" <arg type='as' name='actions'/>"
|
|
" </signal>"
|
|
" </interface>"
|
|
"</node>";
|
|
|
|
static const char prop_sep[] = ":";
|
|
|
|
static QByteArray ibus_property_args_to_propstr(const char *key, const char *label, const char *icon, const char *tooltip, const char *hint = "")
|
|
{
|
|
QByteArray propstr("/IBus/");
|
|
QByteArray str(key);
|
|
str.replace(':', '!');
|
|
|
|
App *app = static_cast<App *>(qApp);
|
|
|
|
propstr += str;
|
|
propstr += prop_sep;
|
|
propstr += QByteArray(label).replace(':', '-').constData();
|
|
propstr += prop_sep;
|
|
propstr += app->normalizeIconName(QByteArray(icon).replace(':', '-'));
|
|
propstr += prop_sep;
|
|
propstr += QByteArray(tooltip).replace(':', '-').constData();
|
|
propstr += prop_sep;
|
|
propstr += QByteArray(hint).replace(':', '-').constData();
|
|
|
|
return propstr;
|
|
}
|
|
|
|
static QByteArray ibus_engine_desc_to_logo_propstr(IBusEngineDesc *engine)
|
|
{
|
|
const gchar *label = "IBus";
|
|
const gchar *tooltip = "";
|
|
const gchar *icon = "input-keyboard";
|
|
|
|
gchar xkbLabel[3];
|
|
if (engine) {
|
|
const gchar *iconname = ibus_engine_desc_get_icon(engine);
|
|
if (iconname && iconname[0]) {
|
|
icon = iconname;
|
|
}
|
|
|
|
if (strncmp("xkb:", ibus_engine_desc_get_name(engine), 4) == 0) {
|
|
strncpy(xkbLabel, ibus_engine_desc_get_name(engine) + 4, 2);
|
|
xkbLabel[2] = 0;
|
|
int i = 0;
|
|
while (xkbLabel[i]) {
|
|
if (xkbLabel[i] == ':') {
|
|
xkbLabel[i] = 0;
|
|
}
|
|
i++;
|
|
}
|
|
label = xkbLabel;
|
|
icon = "";
|
|
}
|
|
|
|
const gchar *longname = ibus_engine_desc_get_longname(engine);
|
|
if (longname && longname[0]) {
|
|
tooltip = longname;
|
|
}
|
|
}
|
|
|
|
return ibus_property_args_to_propstr("Logo", label, icon, tooltip);
|
|
}
|
|
|
|
static QByteArray ibus_property_to_propstr(IBusProperty *property, gboolean useSymbol)
|
|
{
|
|
const gchar *label = nullptr;
|
|
const gchar *tooltip = ibus_text_get_text(ibus_property_get_tooltip(property));
|
|
const gchar *icon = ibus_property_get_icon(property);
|
|
|
|
if (useSymbol) {
|
|
label = ibus_text_get_text(ibus_property_get_symbol(property));
|
|
if (!label || label[0] == '\0') {
|
|
label = ibus_text_get_text(ibus_property_get_label(property));
|
|
}
|
|
} else {
|
|
label = ibus_text_get_text(ibus_property_get_label(property));
|
|
}
|
|
|
|
const char *hint = "";
|
|
if (ibus_property_get_prop_type(property) == PROP_TYPE_TOGGLE) {
|
|
if (ibus_property_get_state(property) != PROP_STATE_CHECKED) {
|
|
hint = "disable";
|
|
}
|
|
} else if (ibus_property_get_prop_type(property) == PROP_TYPE_RADIO) {
|
|
if (ibus_property_get_state(property) == PROP_STATE_CHECKED) {
|
|
hint = "checked";
|
|
}
|
|
}
|
|
|
|
return ibus_property_args_to_propstr(ibus_property_get_key(property), label, icon, tooltip, hint);
|
|
}
|
|
|
|
static QByteArray ibus_engine_desc_args_to_propstr(const char *name, const char *language, const char *longname, const char *icon, const char *description)
|
|
{
|
|
QByteArray propstr("/IBus/Engine/");
|
|
QByteArray data(name);
|
|
data.replace(':', '!');
|
|
propstr += data;
|
|
propstr += prop_sep;
|
|
if (language) {
|
|
propstr += language;
|
|
propstr += " - ";
|
|
}
|
|
propstr += longname;
|
|
propstr += prop_sep;
|
|
propstr += icon;
|
|
propstr += prop_sep;
|
|
propstr += description;
|
|
return propstr;
|
|
}
|
|
|
|
static QByteArray ibus_engine_desc_to_propstr(IBusEngineDesc *engine_desc)
|
|
{
|
|
return ibus_engine_desc_args_to_propstr(ibus_engine_desc_get_name(engine_desc),
|
|
ibus_engine_desc_get_language(engine_desc),
|
|
ibus_engine_desc_get_longname(engine_desc),
|
|
ibus_engine_desc_get_icon(engine_desc),
|
|
ibus_engine_desc_get_description(engine_desc));
|
|
}
|
|
|
|
static void impanel_get_default_engine(IBusPanelImpanel *impanel, char ***pengine_names, gsize *plen)
|
|
{
|
|
GList *engines = ibus_bus_list_engines(impanel->bus);
|
|
if (!engines) {
|
|
*pengine_names = g_new0(gchar *, 2);
|
|
*plen = 1;
|
|
(*pengine_names)[0] = g_strdup("xkb:us::eng");
|
|
return;
|
|
}
|
|
|
|
QList<QByteArray> engineList;
|
|
impanel->xkbLayoutManager->getLayout();
|
|
QStringList layouts = impanel->xkbLayoutManager->defaultLayout().split(QLatin1Char{','});
|
|
QStringList variants = impanel->xkbLayoutManager->defaultVariant().split(QLatin1Char{','});
|
|
|
|
for (int i = 0; i < layouts.size(); i++) {
|
|
QString variant;
|
|
if (i < variants.size()) {
|
|
variant = variants[i];
|
|
}
|
|
|
|
for (GList *engine = g_list_first(engines); engine != nullptr; engine = g_list_next(engine)) {
|
|
IBusEngineDesc *desc = IBUS_ENGINE_DESC(engine->data);
|
|
QByteArray name = ibus_engine_desc_get_name(desc);
|
|
if (!name.startsWith("xkb:")) {
|
|
continue;
|
|
}
|
|
|
|
if (QLatin1String(ibus_engine_desc_get_layout(desc)) == layouts[i] && QLatin1String(ibus_engine_desc_get_layout_variant(desc)) == variant) {
|
|
engineList << name;
|
|
}
|
|
}
|
|
}
|
|
const char *locale = setlocale(LC_CTYPE, nullptr);
|
|
if (!locale) {
|
|
locale = "C";
|
|
}
|
|
|
|
QStringList localeList = QString::fromLocal8Bit(locale).split(QLatin1Char{'.'});
|
|
const QString lang = localeList.size() > 0 ? localeList.at(0) : QString{};
|
|
|
|
bool added = false;
|
|
for (GList *engine = g_list_first(engines); engine != nullptr; engine = g_list_next(engine)) {
|
|
IBusEngineDesc *desc = IBUS_ENGINE_DESC(engine->data);
|
|
QByteArray name = ibus_engine_desc_get_name(desc);
|
|
if (name.startsWith("xkb:")) {
|
|
continue;
|
|
}
|
|
|
|
if (QLatin1String(ibus_engine_desc_get_language(desc)) == lang && ibus_engine_desc_get_rank(desc) > 0) {
|
|
engineList << name;
|
|
added = true;
|
|
}
|
|
}
|
|
|
|
if (!added) {
|
|
localeList = QString(lang).split(QLatin1Char{'_'});
|
|
QString _lang = localeList.size() > 0 ? localeList.at(0) : QString{};
|
|
|
|
for (GList *engine = g_list_first(engines); engine != nullptr; engine = g_list_next(engine)) {
|
|
IBusEngineDesc *desc = IBUS_ENGINE_DESC(engine->data);
|
|
QByteArray name = ibus_engine_desc_get_name(desc);
|
|
if (name.startsWith("xkb:")) {
|
|
continue;
|
|
}
|
|
|
|
if (QLatin1String(ibus_engine_desc_get_language(desc)) == _lang && ibus_engine_desc_get_rank(desc) > 0) {
|
|
engineList << name;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (GList *engine = g_list_first(engines); engine != nullptr; engine = g_list_next(engine)) {
|
|
IBusEngineDesc *desc = IBUS_ENGINE_DESC(engine->data);
|
|
g_object_unref(desc);
|
|
}
|
|
|
|
g_list_free(engines);
|
|
|
|
if (engineList.size() == 0) {
|
|
*pengine_names = g_new0(gchar *, 2);
|
|
*plen = 1;
|
|
(*pengine_names)[0] = g_strdup("xkb:us::eng");
|
|
return;
|
|
} else {
|
|
*pengine_names = g_new0(gchar *, engineList.size() + 1);
|
|
*plen = engineList.size();
|
|
size_t i = 0;
|
|
for (const QByteArray &name : std::as_const(engineList)) {
|
|
(*pengine_names)[i] = g_strdup(name.constData());
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool contains(gchar **strlist, const gchar *str)
|
|
{
|
|
for (; strlist; ++strlist) {
|
|
if (g_strcmp0(*strlist, str) == 0)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static void impanel_update_engines(IBusPanelImpanel *impanel, GVariant *var_engines)
|
|
{
|
|
gchar **engine_names = nullptr;
|
|
size_t len = 0;
|
|
if (var_engines) {
|
|
engine_names = g_variant_dup_strv(var_engines, &len);
|
|
}
|
|
if (len == 0) {
|
|
g_strfreev(engine_names);
|
|
engine_names = nullptr;
|
|
}
|
|
|
|
if (!engine_names) {
|
|
impanel_get_default_engine(impanel, &engine_names, &len);
|
|
GVariant *var = g_variant_new_strv(engine_names, len);
|
|
g_settings_set_value(impanel->settings_general, "preload-engines", var);
|
|
}
|
|
|
|
IBusEngineDesc **engines = ibus_bus_get_engines_by_names(impanel->bus, engine_names);
|
|
|
|
impanel->engineManager->setEngines(engines);
|
|
if (engines && engines[0]
|
|
&& (!ibus_bus_get_global_engine(impanel->bus) || !contains(engine_names, ibus_engine_desc_get_name(ibus_bus_get_global_engine(impanel->bus))))) {
|
|
ibus_bus_set_global_engine(impanel->bus, ibus_engine_desc_get_name(engines[0]));
|
|
}
|
|
g_strfreev(engine_names);
|
|
|
|
impanel->app->setDoGrab(len > 1);
|
|
}
|
|
|
|
static void impanel_update_engines_order(IBusPanelImpanel *impanel, GVariant *var_engines)
|
|
{
|
|
const gchar **engine_names = nullptr;
|
|
size_t len = 0;
|
|
engine_names = g_variant_get_strv(var_engines, &len);
|
|
if (len) {
|
|
impanel->engineManager->setOrder(engine_names, len);
|
|
|
|
if (impanel->engineManager->engines()) {
|
|
ibus_bus_set_global_engine(impanel->bus, ibus_engine_desc_get_name(impanel->engineManager->engines()[0]));
|
|
}
|
|
}
|
|
g_free(engine_names);
|
|
}
|
|
|
|
static void impanel_update_triggers(IBusPanelImpanel *impanel, GVariant *variant)
|
|
{
|
|
gchar **triggers = nullptr;
|
|
size_t len = 0;
|
|
if (variant) {
|
|
triggers = g_variant_dup_strv(variant, &len);
|
|
}
|
|
if (len == 0) {
|
|
g_strfreev(triggers);
|
|
triggers = nullptr;
|
|
}
|
|
if (!triggers) {
|
|
triggers = g_new0(gchar *, 2);
|
|
len = 1;
|
|
triggers[0] = g_strdup("<Super>space");
|
|
}
|
|
|
|
QList<QPair<uint, uint>> triggersList;
|
|
for (size_t i = 0; i < len; i++) {
|
|
guint key = 0;
|
|
GdkModifierType mod = (GdkModifierType)0;
|
|
_gtk_accelerator_parse(triggers[i], &key, &mod);
|
|
if (key) {
|
|
triggersList << qMakePair<uint, uint>(key, (uint)mod);
|
|
}
|
|
}
|
|
impanel->app->setTriggerKeys(triggersList);
|
|
}
|
|
|
|
static void impanel_update_use_system_keyboard_layout(IBusPanelImpanel *impanel, GVariant *variant)
|
|
{
|
|
impanel->useSystemKeyboardLayout = g_variant_get_boolean(variant);
|
|
}
|
|
static void impanel_update_use_global_engine(IBusPanelImpanel *impanel, GVariant *variant)
|
|
{
|
|
impanel->engineManager->setUseGlobalEngine(g_variant_get_boolean(variant));
|
|
}
|
|
|
|
static void impanel_update_latin_layouts(IBusPanelImpanel *impanel, GVariant *variant)
|
|
{
|
|
if (!variant) {
|
|
return;
|
|
}
|
|
gsize length;
|
|
const gchar **variants = g_variant_get_strv(variant, &length);
|
|
|
|
impanel->xkbLayoutManager->setLatinLayouts(variants, length);
|
|
g_free(variants);
|
|
}
|
|
|
|
static void impanel_settings_changed_callback(GSettings *settings, const gchar *key, gpointer user_data)
|
|
{
|
|
IBusPanelImpanel *impanel = ((IBusPanelImpanel *)user_data);
|
|
gchar *schema = nullptr;
|
|
GVariant *value = g_settings_get_value(settings, key);
|
|
|
|
g_object_get(G_OBJECT(settings), "schema", &schema, NULL);
|
|
|
|
if (g_strcmp0(schema, IBUS_SCHEMA_GENERAL) == 0 && g_strcmp0(key, "preload-engines") == 0) {
|
|
impanel_update_engines(impanel, value);
|
|
} else if (g_strcmp0(schema, IBUS_SCHEMA_HOTKEY) == 0 && g_strcmp0(key, "triggers") == 0) {
|
|
impanel_update_triggers(impanel, value);
|
|
} else if (g_strcmp0(schema, IBUS_SCHEMA_GENERAL) == 0 && g_strcmp0(key, "use-system-keyboard-layout") == 0) {
|
|
impanel_update_use_system_keyboard_layout(impanel, value);
|
|
} else if (g_strcmp0(schema, IBUS_SCHEMA_GENERAL) == 0 && g_strcmp0(key, "use-global-engine") == 0) {
|
|
impanel_update_use_global_engine(impanel, value);
|
|
}
|
|
g_free(schema);
|
|
}
|
|
|
|
static void impanel_exit_callback(GDBusConnection *connection,
|
|
const gchar *sender_name,
|
|
const gchar *object_path,
|
|
const gchar *interface_name,
|
|
const gchar *signal_name,
|
|
GVariant *parameters,
|
|
gpointer user_data)
|
|
{
|
|
Q_UNUSED(connection);
|
|
Q_UNUSED(sender_name);
|
|
Q_UNUSED(object_path);
|
|
Q_UNUSED(interface_name);
|
|
Q_UNUSED(signal_name);
|
|
Q_UNUSED(parameters);
|
|
IBusPanelImpanel *impanel = ((IBusPanelImpanel *)user_data);
|
|
if (impanel->bus) {
|
|
ibus_bus_exit(impanel->bus, FALSE);
|
|
}
|
|
}
|
|
|
|
static void impanel_panel_created_callback(GDBusConnection *connection,
|
|
const gchar *sender_name,
|
|
const gchar *object_path,
|
|
const gchar *interface_name,
|
|
const gchar *signal_name,
|
|
GVariant *parameters,
|
|
gpointer user_data)
|
|
{
|
|
Q_UNUSED(connection);
|
|
Q_UNUSED(sender_name);
|
|
Q_UNUSED(object_path);
|
|
Q_UNUSED(interface_name);
|
|
Q_UNUSED(signal_name);
|
|
Q_UNUSED(parameters);
|
|
IBusPanelImpanel *impanel = ((IBusPanelImpanel *)user_data);
|
|
ibus_panel_impanel_real_register_properties(impanel);
|
|
}
|
|
|
|
static void impanel_set_engine(IBusPanelImpanel *impanel, const char *name)
|
|
{
|
|
if (!name || !name[0]) {
|
|
return;
|
|
}
|
|
if (ibus_bus_set_global_engine(impanel->bus, name)) {
|
|
if (!impanel->useSystemKeyboardLayout) {
|
|
IBusEngineDesc *engine_desc = ibus_bus_get_global_engine(impanel->bus);
|
|
if (engine_desc) {
|
|
impanel->xkbLayoutManager->setLayout(engine_desc);
|
|
}
|
|
g_object_unref(engine_desc);
|
|
}
|
|
impanel->engineManager->setCurrentEngine(name);
|
|
} else {
|
|
qDebug() << "set engine failed.";
|
|
}
|
|
}
|
|
|
|
static void impanel_trigger_property_callback(GDBusConnection *connection,
|
|
const gchar *sender_name,
|
|
const gchar *object_path,
|
|
const gchar *interface_name,
|
|
const gchar *signal_name,
|
|
GVariant *parameters,
|
|
gpointer user_data)
|
|
{
|
|
Q_UNUSED(connection);
|
|
Q_UNUSED(sender_name);
|
|
Q_UNUSED(object_path);
|
|
Q_UNUSED(interface_name);
|
|
Q_UNUSED(signal_name);
|
|
IBusPanelImpanel *impanel = IBUS_PANEL_IMPANEL(user_data);
|
|
gchar *s0 = nullptr;
|
|
g_variant_get(parameters, "(s)", &s0);
|
|
if (!s0 || strlen(s0) <= 6)
|
|
return;
|
|
QByteArray prop_key(s0 + 6); // +6 to skip "/IBus/"
|
|
prop_key.replace('!', ':');
|
|
if (g_ascii_strncasecmp(prop_key.constData(), "Logo", 4) == 0)
|
|
ibus_panel_impanel_exec_im_menu(impanel);
|
|
else if (g_ascii_strncasecmp(prop_key.constData(), "Engine/", 7) == 0) {
|
|
impanel_set_engine(impanel, prop_key.constData() + 7);
|
|
} else {
|
|
IBusProperty *property = impanel->propManager->property(prop_key.constData());
|
|
if (property) {
|
|
IBusPropState newstate = ibus_property_get_state(property);
|
|
switch (ibus_property_get_prop_type(property)) {
|
|
case PROP_TYPE_RADIO:
|
|
case PROP_TYPE_TOGGLE:
|
|
if (ibus_property_get_prop_type(property) == PROP_TYPE_TOGGLE) {
|
|
if (newstate == PROP_STATE_CHECKED)
|
|
newstate = PROP_STATE_UNCHECKED;
|
|
else if (newstate == PROP_STATE_UNCHECKED)
|
|
newstate = PROP_STATE_CHECKED;
|
|
} else if (ibus_property_get_prop_type(property) == PROP_TYPE_RADIO) {
|
|
newstate = PROP_STATE_CHECKED;
|
|
}
|
|
Q_FALLTHROUGH();
|
|
case PROP_TYPE_NORMAL:
|
|
ibus_property_set_state(property, newstate);
|
|
ibus_panel_service_property_activate((IBusPanelService *)impanel, prop_key.constData(), newstate);
|
|
break;
|
|
case PROP_TYPE_MENU:
|
|
ibus_panel_impanel_exec_menu(impanel, ibus_property_get_sub_props(property));
|
|
case PROP_TYPE_SEPARATOR:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} else {
|
|
ibus_panel_service_property_activate((IBusPanelService *)impanel, prop_key.constData(), PROP_STATE_CHECKED);
|
|
}
|
|
}
|
|
g_free(s0);
|
|
}
|
|
|
|
static void impanel_select_candidate_callback(GDBusConnection *connection,
|
|
const gchar *sender_name,
|
|
const gchar *object_path,
|
|
const gchar *interface_name,
|
|
const gchar *signal_name,
|
|
GVariant *parameters,
|
|
gpointer user_data)
|
|
{
|
|
Q_UNUSED(connection);
|
|
Q_UNUSED(sender_name);
|
|
Q_UNUSED(object_path);
|
|
Q_UNUSED(interface_name);
|
|
Q_UNUSED(signal_name);
|
|
|
|
gint i;
|
|
g_variant_get(parameters, "(i)", &i);
|
|
IBusPanelImpanel *impanel = IBUS_PANEL_IMPANEL(user_data);
|
|
ibus_panel_service_candidate_clicked((IBusPanelService *)impanel, i, 0, 0);
|
|
}
|
|
|
|
static void impanel_prev_page_callback(GDBusConnection *connection,
|
|
const gchar *sender_name,
|
|
const gchar *object_path,
|
|
const gchar *interface_name,
|
|
const gchar *signal_name,
|
|
GVariant *parameters,
|
|
gpointer user_data)
|
|
{
|
|
Q_UNUSED(connection);
|
|
Q_UNUSED(sender_name);
|
|
Q_UNUSED(object_path);
|
|
Q_UNUSED(interface_name);
|
|
Q_UNUSED(signal_name);
|
|
Q_UNUSED(parameters);
|
|
|
|
IBusPanelImpanel *impanel = IBUS_PANEL_IMPANEL(user_data);
|
|
ibus_panel_service_page_up((IBusPanelService *)impanel);
|
|
}
|
|
|
|
static void impanel_next_page_callback(GDBusConnection *connection,
|
|
const gchar *sender_name,
|
|
const gchar *object_path,
|
|
const gchar *interface_name,
|
|
const gchar *signal_name,
|
|
GVariant *parameters,
|
|
gpointer user_data)
|
|
{
|
|
Q_UNUSED(connection);
|
|
Q_UNUSED(sender_name);
|
|
Q_UNUSED(object_path);
|
|
Q_UNUSED(interface_name);
|
|
Q_UNUSED(signal_name);
|
|
Q_UNUSED(parameters);
|
|
|
|
IBusPanelImpanel *impanel = IBUS_PANEL_IMPANEL(user_data);
|
|
ibus_panel_service_page_down((IBusPanelService *)impanel);
|
|
}
|
|
|
|
static void impanel_configure_callback(GDBusConnection *connection,
|
|
const gchar *sender_name,
|
|
const gchar *object_path,
|
|
const gchar *interface_name,
|
|
const gchar *signal_name,
|
|
GVariant *parameters,
|
|
gpointer user_data)
|
|
{
|
|
Q_UNUSED(connection);
|
|
Q_UNUSED(sender_name);
|
|
Q_UNUSED(object_path);
|
|
Q_UNUSED(interface_name);
|
|
Q_UNUSED(signal_name);
|
|
Q_UNUSED(parameters);
|
|
Q_UNUSED(user_data);
|
|
pid_t pid = fork();
|
|
if (pid == 0) {
|
|
execlp("ibus-setup", "ibus-setup", (char *)nullptr);
|
|
exit(0);
|
|
}
|
|
}
|
|
|
|
static void on_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
|
|
{
|
|
Q_UNUSED(name);
|
|
IBusPanelImpanel *impanel = ((IBusPanelImpanel *)user_data);
|
|
impanel->conn = connection;
|
|
|
|
g_dbus_connection_register_object(connection,
|
|
"/kimpanel",
|
|
introspection_data->interfaces[0],
|
|
nullptr, /*&interface_vtable*/
|
|
nullptr, /* user_data */
|
|
nullptr, /* user_data_free_func */
|
|
nullptr); /* GError** */
|
|
|
|
g_dbus_connection_signal_subscribe(connection,
|
|
"org.kde.impanel",
|
|
"org.kde.impanel",
|
|
"TriggerProperty",
|
|
"/org/kde/impanel",
|
|
nullptr,
|
|
G_DBUS_SIGNAL_FLAGS_NONE,
|
|
impanel_trigger_property_callback,
|
|
user_data,
|
|
nullptr);
|
|
g_dbus_connection_signal_subscribe(connection,
|
|
"org.kde.impanel",
|
|
"org.kde.impanel",
|
|
"SelectCandidate",
|
|
"/org/kde/impanel",
|
|
nullptr,
|
|
G_DBUS_SIGNAL_FLAGS_NONE,
|
|
impanel_select_candidate_callback,
|
|
user_data,
|
|
nullptr);
|
|
g_dbus_connection_signal_subscribe(connection,
|
|
"org.kde.impanel",
|
|
"org.kde.impanel",
|
|
"LookupTablePageUp",
|
|
"/org/kde/impanel",
|
|
nullptr,
|
|
G_DBUS_SIGNAL_FLAGS_NONE,
|
|
impanel_prev_page_callback,
|
|
user_data,
|
|
nullptr);
|
|
g_dbus_connection_signal_subscribe(connection,
|
|
"org.kde.impanel",
|
|
"org.kde.impanel",
|
|
"LookupTablePageDown",
|
|
"/org/kde/impanel",
|
|
nullptr,
|
|
G_DBUS_SIGNAL_FLAGS_NONE,
|
|
impanel_next_page_callback,
|
|
user_data,
|
|
nullptr);
|
|
g_dbus_connection_signal_subscribe(connection,
|
|
"org.kde.impanel",
|
|
"org.kde.impanel",
|
|
"PanelCreated",
|
|
"/org/kde/impanel",
|
|
nullptr,
|
|
G_DBUS_SIGNAL_FLAGS_NONE,
|
|
impanel_panel_created_callback,
|
|
user_data,
|
|
nullptr);
|
|
g_dbus_connection_signal_subscribe(connection,
|
|
"org.kde.impanel",
|
|
"org.kde.impanel",
|
|
"Exit",
|
|
"/org/kde/impanel",
|
|
nullptr,
|
|
G_DBUS_SIGNAL_FLAGS_NONE,
|
|
impanel_exit_callback,
|
|
user_data,
|
|
nullptr);
|
|
g_dbus_connection_signal_subscribe(connection,
|
|
"org.kde.impanel",
|
|
"org.kde.impanel",
|
|
"Configure",
|
|
"/org/kde/impanel",
|
|
nullptr,
|
|
G_DBUS_SIGNAL_FLAGS_NONE,
|
|
impanel_configure_callback,
|
|
user_data,
|
|
nullptr);
|
|
|
|
GVariant *var_engines = g_settings_get_value(impanel->settings_general, "preload-engines");
|
|
impanel_update_engines(impanel, var_engines);
|
|
if (var_engines) {
|
|
g_variant_unref(var_engines);
|
|
}
|
|
|
|
var_engines = g_settings_get_value(impanel->settings_general, "engines-order");
|
|
if (var_engines) {
|
|
impanel_update_engines_order(impanel, var_engines);
|
|
g_variant_unref(var_engines);
|
|
}
|
|
|
|
GVariant *var_triggers = g_settings_get_value(impanel->settings_hotkey, "triggers");
|
|
impanel_update_triggers(impanel, var_triggers);
|
|
if (var_triggers) {
|
|
g_variant_unref(var_triggers);
|
|
}
|
|
|
|
GVariant *var_layouts = g_settings_get_value(impanel->settings_general, "xkb-latin-layouts");
|
|
if (var_layouts) {
|
|
impanel_update_latin_layouts(impanel, var_layouts);
|
|
g_variant_unref(var_layouts);
|
|
}
|
|
|
|
GVariant *var = g_settings_get_value(impanel->settings_general, "use-system-keyboard-layout");
|
|
if (var) {
|
|
impanel_update_use_system_keyboard_layout(impanel, var);
|
|
g_variant_unref(var);
|
|
}
|
|
|
|
var = g_settings_get_value(impanel->settings_general, "use-global-engine");
|
|
if (var) {
|
|
impanel_update_use_global_engine(impanel, var);
|
|
g_variant_unref(var);
|
|
}
|
|
|
|
ibus_panel_impanel_real_register_properties(impanel);
|
|
}
|
|
|
|
static void on_name_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
|
|
{
|
|
Q_UNUSED(connection);
|
|
Q_UNUSED(name);
|
|
Q_UNUSED(user_data);
|
|
}
|
|
|
|
static void on_name_lost(GDBusConnection *connection, const gchar *name, gpointer user_data)
|
|
{
|
|
Q_UNUSED(connection);
|
|
Q_UNUSED(name);
|
|
Q_UNUSED(user_data);
|
|
exit(1);
|
|
}
|
|
|
|
G_DEFINE_TYPE(IBusPanelImpanel, ibus_panel_impanel, IBUS_TYPE_PANEL_SERVICE)
|
|
|
|
static void ibus_panel_impanel_class_init(IBusPanelImpanelClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
|
|
|
// clang-format off
|
|
IBUS_OBJECT_CLASS (object_class)->destroy = (IBusObjectDestroyFunc) ibus_panel_impanel_destroy;
|
|
IBUS_PANEL_SERVICE_CLASS (object_class)->focus_in = ibus_panel_impanel_focus_in;
|
|
IBUS_PANEL_SERVICE_CLASS (object_class)->focus_out = ibus_panel_impanel_focus_out;
|
|
IBUS_PANEL_SERVICE_CLASS (object_class)->register_properties = ibus_panel_impanel_register_properties;
|
|
IBUS_PANEL_SERVICE_CLASS (object_class)->set_cursor_location = ibus_panel_impanel_set_cursor_location;
|
|
IBUS_PANEL_SERVICE_CLASS (object_class)->update_auxiliary_text = ibus_panel_impanel_update_auxiliary_text;
|
|
IBUS_PANEL_SERVICE_CLASS (object_class)->update_lookup_table = ibus_panel_impanel_update_lookup_table;
|
|
IBUS_PANEL_SERVICE_CLASS (object_class)->update_preedit_text = ibus_panel_impanel_update_preedit_text;
|
|
IBUS_PANEL_SERVICE_CLASS (object_class)->update_property = ibus_panel_impanel_update_property;
|
|
IBUS_PANEL_SERVICE_CLASS (object_class)->cursor_down_lookup_table = ibus_panel_impanel_cursor_down_lookup_table;
|
|
IBUS_PANEL_SERVICE_CLASS (object_class)->cursor_up_lookup_table = ibus_panel_impanel_cursor_up_lookup_table;
|
|
IBUS_PANEL_SERVICE_CLASS (object_class)->hide_auxiliary_text = ibus_panel_impanel_hide_auxiliary_text;
|
|
IBUS_PANEL_SERVICE_CLASS (object_class)->hide_language_bar = ibus_panel_impanel_hide_language_bar;
|
|
IBUS_PANEL_SERVICE_CLASS (object_class)->hide_lookup_table = ibus_panel_impanel_hide_lookup_table;
|
|
IBUS_PANEL_SERVICE_CLASS (object_class)->hide_preedit_text = ibus_panel_impanel_hide_preedit_text;
|
|
IBUS_PANEL_SERVICE_CLASS (object_class)->page_down_lookup_table = ibus_panel_impanel_page_down_lookup_table;
|
|
IBUS_PANEL_SERVICE_CLASS (object_class)->page_up_lookup_table = ibus_panel_impanel_page_up_lookup_table;
|
|
IBUS_PANEL_SERVICE_CLASS (object_class)->reset = ibus_panel_impanel_reset;
|
|
IBUS_PANEL_SERVICE_CLASS (object_class)->show_auxiliary_text = ibus_panel_impanel_show_auxiliary_text;
|
|
IBUS_PANEL_SERVICE_CLASS (object_class)->show_language_bar = ibus_panel_impanel_show_language_bar;
|
|
IBUS_PANEL_SERVICE_CLASS (object_class)->show_lookup_table = ibus_panel_impanel_show_lookup_table;
|
|
IBUS_PANEL_SERVICE_CLASS (object_class)->show_preedit_text = ibus_panel_impanel_show_preedit_text;
|
|
IBUS_PANEL_SERVICE_CLASS (object_class)->start_setup = ibus_panel_impanel_start_setup;
|
|
IBUS_PANEL_SERVICE_CLASS (object_class)->state_changed = ibus_panel_impanel_state_changed;
|
|
// clang-format on
|
|
}
|
|
|
|
static void ibus_panel_impanel_init(IBusPanelImpanel *impanel)
|
|
{
|
|
impanel->bus = nullptr;
|
|
impanel->app = nullptr;
|
|
impanel->useSystemKeyboardLayout = false;
|
|
impanel->selected = -1;
|
|
|
|
introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, nullptr);
|
|
owner_id = g_bus_own_name(G_BUS_TYPE_SESSION,
|
|
"org.kde.kimpanel.inputmethod",
|
|
G_BUS_NAME_OWNER_FLAGS_REPLACE,
|
|
on_bus_acquired,
|
|
on_name_acquired,
|
|
on_name_lost,
|
|
impanel,
|
|
nullptr);
|
|
|
|
impanel->propManager = new PropertyManager;
|
|
impanel->engineManager = new EngineManager;
|
|
impanel->xkbLayoutManager = new XkbLayoutManager;
|
|
impanel->settings_general = g_settings_new(IBUS_SCHEMA_GENERAL);
|
|
impanel->settings_hotkey = g_settings_new(IBUS_SCHEMA_HOTKEY);
|
|
g_signal_connect(impanel->settings_general, "changed", G_CALLBACK(impanel_settings_changed_callback), impanel);
|
|
g_signal_connect(impanel->settings_hotkey, "changed", G_CALLBACK(impanel_settings_changed_callback), impanel);
|
|
}
|
|
|
|
static void ibus_panel_impanel_destroy(IBusPanelImpanel *impanel)
|
|
{
|
|
delete impanel->propManager;
|
|
impanel->propManager = nullptr;
|
|
delete impanel->engineManager;
|
|
impanel->engineManager = nullptr;
|
|
delete impanel->xkbLayoutManager;
|
|
impanel->xkbLayoutManager = nullptr;
|
|
|
|
g_signal_handlers_disconnect_by_func(impanel->settings_general, (gpointer)impanel_settings_changed_callback, impanel);
|
|
g_signal_handlers_disconnect_by_func(impanel->settings_hotkey, (gpointer)impanel_settings_changed_callback, impanel);
|
|
g_clear_object(&impanel->settings_general);
|
|
g_clear_object(&impanel->settings_hotkey);
|
|
|
|
g_bus_unown_name(owner_id);
|
|
g_dbus_node_info_unref(introspection_data);
|
|
|
|
IBUS_OBJECT_CLASS(ibus_panel_impanel_parent_class)->destroy((IBusObject *)impanel);
|
|
}
|
|
|
|
static void ibus_panel_impanel_focus_in(IBusPanelService *panel, const gchar *input_context_path)
|
|
{
|
|
IBusPanelImpanel *impanel = IBUS_PANEL_IMPANEL(panel);
|
|
if (impanel->app->keyboardGrabbed()) {
|
|
return;
|
|
}
|
|
|
|
auto engine_desc = ibus_bus_get_global_engine(impanel->bus);
|
|
if (engine_desc) {
|
|
impanel_update_logo_by_engine(impanel, engine_desc);
|
|
g_object_unref(engine_desc);
|
|
}
|
|
|
|
impanel->engineManager->setCurrentContext(input_context_path);
|
|
if (!impanel->engineManager->useGlobalEngine()) {
|
|
impanel_set_engine(impanel, impanel->engineManager->currentEngine().toUtf8().constData());
|
|
}
|
|
}
|
|
|
|
static void ibus_panel_impanel_focus_out(IBusPanelService *panel, const gchar *input_context_path)
|
|
{
|
|
Q_UNUSED(panel);
|
|
Q_UNUSED(input_context_path);
|
|
IBusPanelImpanel *impanel = IBUS_PANEL_IMPANEL(panel);
|
|
|
|
if (impanel->app->keyboardGrabbed()) {
|
|
return;
|
|
}
|
|
|
|
if (impanel->engineManager->useGlobalEngine()) {
|
|
return;
|
|
}
|
|
impanel->engineManager->setCurrentContext("");
|
|
}
|
|
|
|
static void ibus_panel_impanel_register_properties(IBusPanelService *panel, IBusPropList *prop_list)
|
|
{
|
|
IBusPanelImpanel *impanel = IBUS_PANEL_IMPANEL(panel);
|
|
impanel->propManager->setProperties(prop_list);
|
|
ibus_panel_impanel_real_register_properties(impanel);
|
|
}
|
|
|
|
static void ibus_panel_impanel_real_register_properties(IBusPanelImpanel *impanel)
|
|
{
|
|
if (!impanel->conn)
|
|
return;
|
|
|
|
IBusProperty *property = nullptr;
|
|
guint i = 0;
|
|
|
|
GVariantBuilder builder;
|
|
g_variant_builder_init(&builder, G_VARIANT_TYPE("as"));
|
|
|
|
if (impanel->selected >= 0 && static_cast<size_t>(impanel->selected) < impanel->engineManager->length()) {
|
|
auto engine_desc = impanel->engineManager->engines()[impanel->selected];
|
|
QByteArray propstr = ibus_engine_desc_to_logo_propstr(engine_desc);
|
|
g_variant_builder_add(&builder, "s", propstr.constData());
|
|
} else {
|
|
QByteArray propstr;
|
|
auto engine_desc = ibus_bus_get_global_engine(impanel->bus);
|
|
if (engine_desc) {
|
|
propstr = ibus_engine_desc_to_logo_propstr(engine_desc);
|
|
g_variant_builder_add(&builder, "s", propstr.constData());
|
|
g_object_unref(engine_desc);
|
|
}
|
|
|
|
IBusPropList *prop_list = impanel->propManager->properties();
|
|
if (prop_list) {
|
|
while ((property = ibus_prop_list_get(prop_list, i)) != nullptr) {
|
|
propstr = ibus_property_to_propstr(property, TRUE);
|
|
g_variant_builder_add(&builder, "s", propstr.constData());
|
|
++i;
|
|
}
|
|
}
|
|
}
|
|
|
|
g_dbus_connection_emit_signal(impanel->conn,
|
|
nullptr,
|
|
"/kimpanel",
|
|
"org.kde.kimpanel.inputmethod",
|
|
"RegisterProperties",
|
|
(g_variant_new("(as)", &builder)),
|
|
nullptr);
|
|
}
|
|
|
|
static void ibus_panel_impanel_set_cursor_location(IBusPanelService *panel, gint x, gint y, gint w, gint h)
|
|
{
|
|
g_dbus_connection_call(IBUS_PANEL_IMPANEL(panel)->conn,
|
|
"org.kde.impanel",
|
|
"/org/kde/impanel",
|
|
"org.kde.impanel2",
|
|
"SetSpotRect",
|
|
(g_variant_new("(iiii)", x, y, w, h)),
|
|
nullptr,
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
-1, /* timeout */
|
|
nullptr,
|
|
nullptr,
|
|
nullptr);
|
|
}
|
|
|
|
static void ibus_panel_impanel_update_auxiliary_text(IBusPanelService *panel, IBusText *text, gboolean visible)
|
|
{
|
|
const gchar *t = ibus_text_get_text(text);
|
|
const gchar *attr = "";
|
|
IBusPanelImpanel *impanel = (IBusPanelImpanel *)panel;
|
|
|
|
if (!impanel->conn)
|
|
return;
|
|
|
|
g_dbus_connection_emit_signal(impanel->conn, nullptr, "/kimpanel", "org.kde.kimpanel.inputmethod", "UpdateAux", (g_variant_new("(ss)", t, attr)), nullptr);
|
|
|
|
if (visible == 0)
|
|
ibus_panel_impanel_hide_auxiliary_text(panel);
|
|
else
|
|
ibus_panel_impanel_show_auxiliary_text(panel);
|
|
}
|
|
|
|
static void ibus_panel_impanel_update_lookup_table(IBusPanelService *panel, IBusLookupTable *lookup_table, gboolean visible)
|
|
{
|
|
IBusPanelImpanel *impanel = IBUS_PANEL_IMPANEL(panel);
|
|
if (!impanel->conn)
|
|
return;
|
|
|
|
guint page_size = ibus_lookup_table_get_page_size(lookup_table);
|
|
guint cursor_pos = ibus_lookup_table_get_cursor_pos(lookup_table);
|
|
guint page = cursor_pos / page_size;
|
|
guint start = page * page_size;
|
|
guint end = start + page_size;
|
|
guint num = ibus_lookup_table_get_number_of_candidates(lookup_table);
|
|
if (end > num) {
|
|
end = num;
|
|
}
|
|
|
|
// fprintf(stderr, "%d ~ %d pgsize %d num %d\n", start, end, page_size, num);
|
|
|
|
guint i;
|
|
|
|
gchar label[16][4]; // WARNING large enough I think --- nihui
|
|
const gchar *candidate;
|
|
|
|
GVariantBuilder builder_labels;
|
|
GVariantBuilder builder_candidates;
|
|
GVariantBuilder builder_attrs;
|
|
g_variant_builder_init(&builder_labels, G_VARIANT_TYPE("as"));
|
|
g_variant_builder_init(&builder_candidates, G_VARIANT_TYPE("as"));
|
|
g_variant_builder_init(&builder_attrs, G_VARIANT_TYPE("as"));
|
|
|
|
const gchar *attr = "";
|
|
for (i = start; i < end; i++) {
|
|
g_snprintf(label[i - start], 4, "%d", (i - start + 1) % 10);
|
|
// NOTE ibus always return NULL for ibus_lookup_table_get_label
|
|
// label = ibus_lookup_table_get_label(lookup_table, i)->text;
|
|
g_variant_builder_add(&builder_labels, "s", label[i - start]);
|
|
|
|
candidate = ibus_text_get_text(ibus_lookup_table_get_candidate(lookup_table, i));
|
|
g_variant_builder_add(&builder_candidates, "s", candidate);
|
|
|
|
g_variant_builder_add(&builder_attrs, "s", attr);
|
|
}
|
|
|
|
gboolean has_prev = 1;
|
|
gboolean has_next = 1;
|
|
|
|
guint cursor_pos_in_page;
|
|
if (ibus_lookup_table_is_cursor_visible(lookup_table))
|
|
cursor_pos_in_page = cursor_pos % page_size;
|
|
else
|
|
cursor_pos_in_page = -1;
|
|
|
|
gint orientation = ibus_lookup_table_get_orientation(lookup_table);
|
|
if (orientation == IBUS_ORIENTATION_HORIZONTAL) {
|
|
orientation = 2;
|
|
} else if (orientation == IBUS_ORIENTATION_VERTICAL) {
|
|
orientation = 1;
|
|
} else {
|
|
orientation = 0;
|
|
}
|
|
|
|
g_dbus_connection_call(
|
|
impanel->conn,
|
|
"org.kde.impanel",
|
|
"/org/kde/impanel",
|
|
"org.kde.impanel2",
|
|
"SetLookupTable",
|
|
(g_variant_new("(asasasbbii)", &builder_labels, &builder_candidates, &builder_attrs, has_prev, has_next, cursor_pos_in_page, orientation)),
|
|
nullptr,
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
-1,
|
|
nullptr,
|
|
nullptr,
|
|
nullptr);
|
|
|
|
if (visible == 0)
|
|
ibus_panel_impanel_hide_lookup_table(panel);
|
|
else
|
|
ibus_panel_impanel_show_lookup_table(panel);
|
|
}
|
|
|
|
static void ibus_panel_impanel_update_preedit_text(IBusPanelService *panel, IBusText *text, guint cursor_pos, gboolean visible)
|
|
{
|
|
IBusPanelImpanel *impanel = IBUS_PANEL_IMPANEL(panel);
|
|
if (!impanel->conn)
|
|
return;
|
|
|
|
const gchar *t = ibus_text_get_text(text);
|
|
const gchar *attr = "";
|
|
|
|
g_dbus_connection_emit_signal(impanel->conn,
|
|
nullptr,
|
|
"/kimpanel",
|
|
"org.kde.kimpanel.inputmethod",
|
|
"UpdatePreeditText",
|
|
(g_variant_new("(ss)", t, attr)),
|
|
nullptr);
|
|
|
|
g_dbus_connection_emit_signal(impanel->conn,
|
|
nullptr,
|
|
"/kimpanel",
|
|
"org.kde.kimpanel.inputmethod",
|
|
"UpdatePreeditCaret",
|
|
(g_variant_new("(i)", cursor_pos)),
|
|
nullptr);
|
|
|
|
if (visible == 0)
|
|
ibus_panel_impanel_hide_preedit_text(panel);
|
|
else
|
|
ibus_panel_impanel_show_preedit_text(panel);
|
|
}
|
|
|
|
static void ibus_panel_impanel_update_property(IBusPanelService *panel, IBusProperty *prop)
|
|
{
|
|
IBusPanelImpanel *impanel = IBUS_PANEL_IMPANEL(panel);
|
|
if (!impanel->conn)
|
|
return;
|
|
|
|
impanel->propManager->updateProperty(prop);
|
|
|
|
QByteArray propstr = ibus_property_to_propstr(prop, TRUE);
|
|
|
|
g_dbus_connection_emit_signal(impanel->conn,
|
|
nullptr,
|
|
"/kimpanel",
|
|
"org.kde.kimpanel.inputmethod",
|
|
"UpdateProperty",
|
|
(g_variant_new("(s)", propstr.constData())),
|
|
nullptr);
|
|
}
|
|
|
|
static void ibus_panel_impanel_cursor_down_lookup_table(IBusPanelService *panel)
|
|
{
|
|
Q_UNUSED(panel);
|
|
}
|
|
|
|
static void ibus_panel_impanel_cursor_up_lookup_table(IBusPanelService *panel)
|
|
{
|
|
Q_UNUSED(panel);
|
|
}
|
|
|
|
static void ibus_panel_impanel_hide_auxiliary_text(IBusPanelService *panel)
|
|
{
|
|
IBusPanelImpanel *impanel = IBUS_PANEL_IMPANEL(panel);
|
|
if (!impanel->conn)
|
|
return;
|
|
gboolean toShow = 0;
|
|
|
|
g_dbus_connection_emit_signal(impanel->conn, nullptr, "/kimpanel", "org.kde.kimpanel.inputmethod", "ShowAux", (g_variant_new("(b)", toShow)), nullptr);
|
|
}
|
|
|
|
static void ibus_panel_impanel_hide_language_bar(IBusPanelService *panel)
|
|
{
|
|
Q_UNUSED(panel);
|
|
}
|
|
|
|
static void ibus_panel_impanel_hide_lookup_table(IBusPanelService *panel)
|
|
{
|
|
IBusPanelImpanel *impanel = IBUS_PANEL_IMPANEL(panel);
|
|
if (!impanel->conn)
|
|
return;
|
|
gboolean toShow = 0;
|
|
|
|
g_dbus_connection_emit_signal(impanel->conn,
|
|
nullptr,
|
|
"/kimpanel",
|
|
"org.kde.kimpanel.inputmethod",
|
|
"ShowLookupTable",
|
|
(g_variant_new("(b)", toShow)),
|
|
nullptr);
|
|
}
|
|
|
|
static void ibus_panel_impanel_hide_preedit_text(IBusPanelService *panel)
|
|
{
|
|
IBusPanelImpanel *impanel = IBUS_PANEL_IMPANEL(panel);
|
|
if (!impanel->conn)
|
|
return;
|
|
gboolean toShow = 0;
|
|
|
|
g_dbus_connection_emit_signal(impanel->conn, nullptr, "/kimpanel", "org.kde.kimpanel.inputmethod", "ShowPreedit", (g_variant_new("(b)", toShow)), nullptr);
|
|
}
|
|
|
|
static void ibus_panel_impanel_page_down_lookup_table(IBusPanelService *panel)
|
|
{
|
|
Q_UNUSED(panel);
|
|
}
|
|
|
|
static void ibus_panel_impanel_page_up_lookup_table(IBusPanelService *panel)
|
|
{
|
|
Q_UNUSED(panel);
|
|
}
|
|
|
|
static void ibus_panel_impanel_reset(IBusPanelService *panel)
|
|
{
|
|
Q_UNUSED(panel);
|
|
}
|
|
|
|
static void ibus_panel_impanel_show_auxiliary_text(IBusPanelService *panel)
|
|
{
|
|
IBusPanelImpanel *impanel = IBUS_PANEL_IMPANEL(panel);
|
|
if (!impanel->conn)
|
|
return;
|
|
gboolean toShow = 1;
|
|
|
|
g_dbus_connection_emit_signal(impanel->conn, nullptr, "/kimpanel", "org.kde.kimpanel.inputmethod", "ShowAux", (g_variant_new("(b)", toShow)), nullptr);
|
|
}
|
|
|
|
static void ibus_panel_impanel_show_language_bar(IBusPanelService *panel)
|
|
{
|
|
Q_UNUSED(panel);
|
|
}
|
|
|
|
static void ibus_panel_impanel_show_lookup_table(IBusPanelService *panel)
|
|
{
|
|
IBusPanelImpanel *impanel = IBUS_PANEL_IMPANEL(panel);
|
|
if (!impanel->conn)
|
|
return;
|
|
gboolean toShow = 1;
|
|
|
|
g_dbus_connection_emit_signal(impanel->conn,
|
|
nullptr,
|
|
"/kimpanel",
|
|
"org.kde.kimpanel.inputmethod",
|
|
"ShowLookupTable",
|
|
(g_variant_new("(b)", toShow)),
|
|
nullptr);
|
|
}
|
|
|
|
static void ibus_panel_impanel_show_preedit_text(IBusPanelService *panel)
|
|
{
|
|
IBusPanelImpanel *impanel = IBUS_PANEL_IMPANEL(panel);
|
|
if (!impanel->conn)
|
|
return;
|
|
gboolean toShow = 1;
|
|
|
|
g_dbus_connection_emit_signal(impanel->conn, nullptr, "/kimpanel", "org.kde.kimpanel.inputmethod", "ShowPreedit", (g_variant_new("(b)", toShow)), nullptr);
|
|
}
|
|
|
|
static void ibus_panel_impanel_start_setup(IBusPanelService *panel)
|
|
{
|
|
Q_UNUSED(panel);
|
|
}
|
|
|
|
static void ibus_panel_impanel_state_changed(IBusPanelService *panel)
|
|
{
|
|
IBusPanelImpanel *impanel = IBUS_PANEL_IMPANEL(panel);
|
|
if (!impanel->conn)
|
|
return;
|
|
|
|
if (impanel->app->keyboardGrabbed()) {
|
|
return;
|
|
}
|
|
|
|
IBusEngineDesc *engine_desc = ibus_bus_get_global_engine(impanel->bus);
|
|
if (!engine_desc) {
|
|
return;
|
|
}
|
|
|
|
impanel_update_logo_by_engine(impanel, engine_desc);
|
|
|
|
g_dbus_connection_emit_signal(impanel->conn, nullptr, "/kimpanel", "org.kde.kimpanel.inputmethod", "Enable", (g_variant_new("(b)", TRUE)), nullptr);
|
|
|
|
impanel->engineManager->moveToFirst(engine_desc);
|
|
QStringList engineList = impanel->engineManager->engineOrder();
|
|
|
|
gchar **engine_names = g_new0(gchar *, engineList.size() + 1);
|
|
size_t i = 0;
|
|
for (const QString &name : std::as_const(engineList)) {
|
|
engine_names[i] = g_strdup(name.toUtf8().constData());
|
|
i++;
|
|
}
|
|
|
|
GVariant *var = g_variant_new_strv(engine_names, engineList.size());
|
|
g_settings_set_value(impanel->settings_general, "engines-order", var);
|
|
g_strfreev(engine_names);
|
|
g_object_unref(engine_desc);
|
|
}
|
|
|
|
static void ibus_panel_impanel_exec_menu(IBusPanelImpanel *impanel, IBusPropList *prop_list)
|
|
{
|
|
if (!impanel->conn)
|
|
return;
|
|
|
|
GVariantBuilder builder;
|
|
g_variant_builder_init(&builder, G_VARIANT_TYPE("as"));
|
|
|
|
int i = 0;
|
|
while (true) {
|
|
IBusProperty *prop = ibus_prop_list_get(prop_list, i);
|
|
if (!prop)
|
|
break;
|
|
QByteArray propstr = ibus_property_to_propstr(prop);
|
|
g_variant_builder_add(&builder, "s", propstr.constData());
|
|
i++;
|
|
}
|
|
|
|
g_dbus_connection_emit_signal(impanel->conn, nullptr, "/kimpanel", "org.kde.kimpanel.inputmethod", "ExecMenu", (g_variant_new("(as)", &builder)), nullptr);
|
|
}
|
|
|
|
static void ibus_panel_impanel_exec_im_menu(IBusPanelImpanel *impanel)
|
|
{
|
|
if (!impanel->conn)
|
|
return;
|
|
|
|
GVariantBuilder builder;
|
|
g_variant_builder_init(&builder, G_VARIANT_TYPE("as"));
|
|
|
|
IBusEngineDesc **engines = impanel->engineManager->engines();
|
|
if (engines) {
|
|
int i = 0;
|
|
while (engines[i]) {
|
|
QByteArray propstr = ibus_engine_desc_to_propstr(engines[i]);
|
|
g_variant_builder_add(&builder, "s", propstr.constData());
|
|
i++;
|
|
}
|
|
}
|
|
|
|
g_dbus_connection_emit_signal(impanel->conn, nullptr, "/kimpanel", "org.kde.kimpanel.inputmethod", "ExecMenu", (g_variant_new("(as)", &builder)), nullptr);
|
|
}
|
|
|
|
IBusPanelImpanel *ibus_panel_impanel_new(GDBusConnection *connection)
|
|
{
|
|
IBusPanelImpanel *panel;
|
|
panel = (IBusPanelImpanel *)g_object_new(IBUS_TYPE_PANEL_IMPANEL, "object-path", IBUS_PATH_PANEL, "connection", connection, NULL);
|
|
return panel;
|
|
}
|