aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.build.yml3
-rw-r--r--CMakeLists.txt3
-rw-r--r--debian/control3
-rw-r--r--po/es.po12
-rw-r--r--po/fi.po26
-rw-r--r--po/hr.po17
-rw-r--r--po/lo.po11
-rw-r--r--po/nb.po12
-rw-r--r--po/oc.po10
-rw-r--r--po/tr.po10
-rw-r--r--po/zh_CN.po12
-rw-r--r--src/keyboard-lomiri.c416
-rw-r--r--src/keyboard-x11.c30
-rw-r--r--src/keyboard.h12
-rw-r--r--src/service.c197
15 files changed, 672 insertions, 102 deletions
diff --git a/.build.yml b/.build.yml
index 3dd505b2..bf96297a 100644
--- a/.build.yml
+++ b/.build.yml
@@ -18,6 +18,7 @@ requires:
- libxklavier
- libxkbcommon
- accountsservice
+ - systemd-libs
# - libayatana-common
debian:
@@ -37,6 +38,7 @@ requires:
- libxkbregistry-dev
- libaccountsservice-dev
- systemd
+ - libudev-dev
# - libayatana-common-dev
# For building libayatana-common:
- liblomiri-url-dispatcher-dev
@@ -54,6 +56,7 @@ requires:
- libxklavier-dev
- libaccountsservice-dev
- systemd
+ - libudev-dev
# - libayatana-common-dev
# - libxkbcommon-dev
# - libxkbregistry-dev
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 37de3115..30fed304 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -38,7 +38,8 @@ add_definitions (-DGETTEXT_PACKAGE="${GETTEXT_PACKAGE}" -DLOCALEDIR="${CMAKE_INS
find_package (PkgConfig REQUIRED)
include (CheckIncludeFile)
include (FindPkgConfig)
-pkg_check_modules(SERVICE_DEPS REQUIRED glib-2.0>=2.36 gio-2.0>=2.36 libayatana-common>=0.9.11 accountsservice xkbcommon>=1.0.3 xkbregistry>=1.0.3)
+
+pkg_check_modules(SERVICE_DEPS REQUIRED glib-2.0>=2.36 gio-2.0>=2.36 libayatana-common>=0.9.11 accountsservice xkbcommon>=1.0.3 xkbregistry>=1.0.3 libudev)
pkg_check_modules(X11_DEPS REQUIRED x11>=1.6.5 libxklavier>=5.3)
include_directories (SYSTEM ${SERVICE_DEPS_INCLUDE_DIRS})
diff --git a/debian/control b/debian/control
index 1bc2b27e..82f08630 100644
--- a/debian/control
+++ b/debian/control
@@ -11,6 +11,7 @@ Build-Depends: cmake,
libxkbcommon-dev (>=1.0.3),
libxkbregistry-dev (>=1.0.3),
libaccountsservice-dev,
+ libudev-dev,
# for packaging
debhelper (>= 10),
dh-systemd | hello,
@@ -28,7 +29,7 @@ Architecture: any
Depends: ${shlibs:Depends},
${misc:Depends},
ayatana-indicator-common,
- matekbd-keyboard-display | gkbd-capplet,
+ matekbd-keyboard-display | gkbd-capplet | tecla,
Description: Ayatana Indicator Keyboard Applet
This package contains the keyboard indicator, which should show as an
icon in the top panel of indicator aware destkop environments.
diff --git a/po/es.po b/po/es.po
index ebab035c..532b2379 100644
--- a/po/es.po
+++ b/po/es.po
@@ -8,16 +8,16 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-23 19:05+0100\n"
-"PO-Revision-Date: 2023-09-16 20:12+0000\n"
-"Last-Translator: gallegonovato <fran-carro@hotmail.es>\n"
-"Language-Team: Spanish <https://hosted.weblate.org/projects/ayatana-"
-"indicators/keyboard-applet/es/>\n"
+"PO-Revision-Date: 2025-06-30 03:06+0000\n"
+"Last-Translator: DP <dprietob@users.noreply.hosted.weblate.org>\n"
+"Language-Team: Spanish <https://hosted.weblate.org/projects/"
+"ayatana-indicators/keyboard-applet/es/>\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 5.0.2\n"
+"X-Generator: Weblate 5.13-dev\n"
#: data/org.ayatana.indicator.keyboard.gschema.xml:1
msgid "Show the language icon in desktop mode."
@@ -53,7 +53,7 @@ msgstr "Disposición de teclado actual"
#: src/service.c:193
msgid "Always show OSK"
-msgstr ""
+msgstr "Mostrar siempre OSK"
#: src/service.c:199
msgid "Keyboard Settings…"
diff --git a/po/fi.po b/po/fi.po
index faaf2651..68f5081e 100644
--- a/po/fi.po
+++ b/po/fi.po
@@ -8,34 +8,36 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-23 19:05+0100\n"
-"PO-Revision-Date: 2021-02-20 01:50+0000\n"
-"Last-Translator: J. Lavoie <j.lavoie@net-c.ca>\n"
-"Language-Team: Finnish <https://hosted.weblate.org/projects/ayatana-"
-"indicators/keyboard-applet/fi/>\n"
+"PO-Revision-Date: 2025-07-18 20:08+0000\n"
+"Last-Translator: Ricky Tigg <ricky.tigg@gmail.com>\n"
+"Language-Team: Finnish <https://hosted.weblate.org/projects/"
+"ayatana-indicators/keyboard-applet/fi/>\n"
"Language: fi\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.5\n"
+"X-Generator: Weblate 5.13-dev\n"
#: data/org.ayatana.indicator.keyboard.gschema.xml:1
msgid "Show the language icon in desktop mode."
-msgstr ""
+msgstr "Näytä kielikuvake työpöytätilassa."
#: data/org.ayatana.indicator.keyboard.gschema.xml:2
msgid ""
"If enabled, the indicator shows the current layout icon. Otherwise, it "
"displays a generic keyboard icon."
msgstr ""
+"Jos käytössä, ilmaisin näyttää nykyisen asettelun kuvakkeen. Muussa "
+"tapauksessa se näyttää yleisen näppäimistökuvakkeen."
#: data/org.ayatana.indicator.keyboard.gschema.xml:3
msgid "Show the language icon in phone mode."
-msgstr ""
+msgstr "Näytä kielikuvake puhelintilassa."
#: data/org.ayatana.indicator.keyboard.gschema.xml:4
msgid "Show the language icon in the greeter."
-msgstr ""
+msgstr "Näytä kielikuvake tervehdysikkunassa."
#: src/service.c:95
msgid "Keyboard"
@@ -43,7 +45,7 @@ msgstr "Näppäimistö"
#: src/service.c:96
msgid "Keyboard layout switcher and settings"
-msgstr ""
+msgstr "Näppäimistöasettelun vaihtaja ja asetukset"
#: src/service.c:133
msgid "Current keyboard layout"
@@ -51,14 +53,12 @@ msgstr "Nykyinen näppäimistöasettelu"
#: src/service.c:193
msgid "Always show OSK"
-msgstr ""
+msgstr "Näytä aina OSK"
#: src/service.c:199
-#, fuzzy
msgid "Keyboard Settings…"
msgstr "Näppäimistön asetukset…"
#: src/service.c:207
-#, fuzzy
msgid "Show Current Layout"
-msgstr "Nykyinen näppäimistöasettelu"
+msgstr "Näytä nykyinen asettelu"
diff --git a/po/hr.po b/po/hr.po
index e19144a1..cef51038 100644
--- a/po/hr.po
+++ b/po/hr.po
@@ -8,17 +8,17 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-23 19:05+0100\n"
-"PO-Revision-Date: 2023-05-21 13:53+0000\n"
+"PO-Revision-Date: 2025-09-15 20:01+0000\n"
"Last-Translator: Milo Ivir <mail@milotype.de>\n"
-"Language-Team: Croatian <https://hosted.weblate.org/projects/ayatana-"
-"indicators/keyboard-applet/hr/>\n"
+"Language-Team: Croatian <https://hosted.weblate.org/projects/"
+"ayatana-indicators/keyboard-applet/hr/>\n"
"Language: hr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
-"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
-"X-Generator: Weblate 4.18-dev\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
+"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Generator: Weblate 5.14-dev\n"
#: data/org.ayatana.indicator.keyboard.gschema.xml:1
msgid "Show the language icon in desktop mode."
@@ -54,13 +54,12 @@ msgstr "Trenutačni raspored tipkovnice"
#: src/service.c:193
msgid "Always show OSK"
-msgstr ""
+msgstr "Uvijek prikaži ekransku tipkovnicu"
#: src/service.c:199
msgid "Keyboard Settings…"
msgstr "Postavke tipkovnice …"
#: src/service.c:207
-#, fuzzy
msgid "Show Current Layout"
-msgstr "Trenutačni raspored tipkovnice"
+msgstr "Prikaži trenutačni raspored"
diff --git a/po/lo.po b/po/lo.po
index 69054a41..f999fa04 100644
--- a/po/lo.po
+++ b/po/lo.po
@@ -8,13 +8,16 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-23 19:05+0100\n"
-"PO-Revision-Date: 2021-01-22 23:28+0100\n"
-"Last-Translator: Automatically generated\n"
-"Language-Team: none\n"
+"PO-Revision-Date: 2025-11-15 03:51+0000\n"
+"Last-Translator: BoneNI <bounkirdni@gmail.com>\n"
+"Language-Team: Lao <https://hosted.weblate.org/projects/ayatana-indicators/"
+"keyboard-applet/lo/>\n"
"Language: lo\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: Weblate 5.15-dev\n"
#: data/org.ayatana.indicator.keyboard.gschema.xml:1
msgid "Show the language icon in desktop mode."
@@ -36,7 +39,7 @@ msgstr ""
#: src/service.c:95
msgid "Keyboard"
-msgstr ""
+msgstr "ແປ້ນພິມ"
#: src/service.c:96
msgid "Keyboard layout switcher and settings"
diff --git a/po/nb.po b/po/nb.po
index c2584400..a80fab9d 100644
--- a/po/nb.po
+++ b/po/nb.po
@@ -8,20 +8,20 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-23 19:05+0100\n"
-"PO-Revision-Date: 2021-02-23 16:50+0000\n"
-"Last-Translator: Allan Nordhøy <epost@anotheragency.no>\n"
-"Language-Team: Norwegian Bokmål <https://hosted.weblate.org/projects/ayatana-"
-"indicators/keyboard-applet/nb_NO/>\n"
+"PO-Revision-Date: 2025-08-26 19:02+0000\n"
+"Last-Translator: Ida Brenna <ida@larald.no>\n"
+"Language-Team: Norwegian Bokmål <https://hosted.weblate.org/projects/"
+"ayatana-indicators/keyboard-applet/nb_NO/>\n"
"Language: nb\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.5\n"
+"X-Generator: Weblate 5.13\n"
#: data/org.ayatana.indicator.keyboard.gschema.xml:1
msgid "Show the language icon in desktop mode."
-msgstr ""
+msgstr "Vis språkikonet i skrivebordsmodus."
#: data/org.ayatana.indicator.keyboard.gschema.xml:2
msgid ""
diff --git a/po/oc.po b/po/oc.po
index 90ff49bc..b4d0ba3b 100644
--- a/po/oc.po
+++ b/po/oc.po
@@ -8,16 +8,16 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-23 19:05+0100\n"
-"PO-Revision-Date: 2023-10-16 04:08+0000\n"
+"PO-Revision-Date: 2025-10-06 16:02+0000\n"
"Last-Translator: Quentin PAGÈS <quentinantonin@free.fr>\n"
-"Language-Team: Occitan <https://hosted.weblate.org/projects/ayatana-"
-"indicators/keyboard-applet/oc/>\n"
+"Language-Team: Occitan <https://hosted.weblate.org/projects/"
+"ayatana-indicators/keyboard-applet/oc/>\n"
"Language: oc\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
-"X-Generator: Weblate 5.1-dev\n"
+"X-Generator: Weblate 5.14-dev\n"
#: data/org.ayatana.indicator.keyboard.gschema.xml:1
msgid "Show the language icon in desktop mode."
@@ -53,7 +53,7 @@ msgstr "Agençament actual del clavièr"
#: src/service.c:193
msgid "Always show OSK"
-msgstr ""
+msgstr "Totjorn afichar lo clavièr virtual"
#: src/service.c:199
msgid "Keyboard Settings…"
diff --git a/po/tr.po b/po/tr.po
index 6e777fe9..7701e79f 100644
--- a/po/tr.po
+++ b/po/tr.po
@@ -8,16 +8,16 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-23 19:05+0100\n"
-"PO-Revision-Date: 2023-09-16 20:12+0000\n"
+"PO-Revision-Date: 2025-10-05 14:01+0000\n"
"Last-Translator: Oğuz Ersen <oguz@ersen.moe>\n"
-"Language-Team: Turkish <https://hosted.weblate.org/projects/ayatana-"
-"indicators/keyboard-applet/tr/>\n"
+"Language-Team: Turkish <https://hosted.weblate.org/projects/"
+"ayatana-indicators/keyboard-applet/tr/>\n"
"Language: tr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 5.0.2\n"
+"X-Generator: Weblate 5.14-dev\n"
#: data/org.ayatana.indicator.keyboard.gschema.xml:1
msgid "Show the language icon in desktop mode."
@@ -53,7 +53,7 @@ msgstr "Geçerli klavye düzeni"
#: src/service.c:193
msgid "Always show OSK"
-msgstr ""
+msgstr "Her zaman ekran klavyesini göster"
#: src/service.c:199
msgid "Keyboard Settings…"
diff --git a/po/zh_CN.po b/po/zh_CN.po
index 2145dfbc..953cb744 100644
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
@@ -8,16 +8,16 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-23 19:05+0100\n"
-"PO-Revision-Date: 2024-04-01 22:37+0000\n"
-"Last-Translator: 复予 <clonewith@qq.com>\n"
-"Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/"
-"ayatana-indicators/keyboard-applet/zh_Hans/>\n"
+"PO-Revision-Date: 2025-07-13 05:01+0000\n"
+"Last-Translator: \"Alioc.\" <hit.177411245@gmail.com>\n"
+"Language-Team: Chinese (Simplified Han script) <https://hosted.weblate.org/"
+"projects/ayatana-indicators/keyboard-applet/zh_Hans/>\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 5.5-dev\n"
+"X-Generator: Weblate 5.13-dev\n"
#: data/org.ayatana.indicator.keyboard.gschema.xml:1
msgid "Show the language icon in desktop mode."
@@ -51,7 +51,7 @@ msgstr "当前键盘布局"
#: src/service.c:193
msgid "Always show OSK"
-msgstr ""
+msgstr "总是显示 OSK"
#: src/service.c:199
msgid "Keyboard Settings…"
diff --git a/src/keyboard-lomiri.c b/src/keyboard-lomiri.c
index c00bc55a..176d576b 100644
--- a/src/keyboard-lomiri.c
+++ b/src/keyboard-lomiri.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2021-2024 Robert Tari <robert@tari.in>
+ * Copyright 2021-2025 Robert Tari <robert@tari.in>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
@@ -17,10 +17,37 @@
#include <act/act.h>
#include <xkbcommon/xkbregistry.h>
#include <glib-object.h>
+#include <libudev.h>
#include "languages.h"
#include "keyboard.h"
#include "system-layouts.h"
+gchar *LOMIRI_TO_ISO[][2] =
+{
+ {"ar", "ara"},
+ {"bn", "bd"},
+ {"bn-probhat", "bd+probhat"},
+ {"bs", "ba"},
+ {"cs", "cz"},
+ {"da", "dk"},
+ {"el", "gr"},
+ {"en", "us"},
+ {"endv", "us+dvorak"},
+ {"eo", "epo"},
+ {"fa", "ir"},
+ {"fr-ch", "ch+fr"},
+ {"gd", "gb+gla"},
+ {"he", "il"},
+ {"ja", "jp"},
+ {"ko", "kr"},
+ {"nb", "no"},
+ {"sl", "si"},
+ {"sr", "rs"},
+ {"sv", "se"},
+ {"uk", "ua"},
+ {NULL, NULL}
+};
+
enum
{
LAYOUT_CHANGED,
@@ -34,9 +61,18 @@ struct _KeyboardPrivate
{
GHashTable *lLayouts;
guint nLayout;
+ guint nLayoutOSK;
GSList *lLayoutRec;
+ GSList *lLayoutRecOSK;
GSList *lUsers;
GSettings *pSettings;
+ struct udev *pUdev;
+ struct udev_monitor *pMonitor;
+ GIOChannel *pChannel;
+ gboolean bHardwareKeyboard;
+ gboolean bSoftwareKeyboard;
+ GSettings *pLomiriSettings;
+ GSettings *pMaliitSettings;
};
typedef KeyboardPrivate priv_t;
@@ -169,24 +205,57 @@ void keyboard_AddSource(Keyboard *pKeyboard)
return;
}
-guint keyboard_GetNumLayouts(Keyboard *pKeyboard)
+guint keyboard_GetNumLayouts(Keyboard *pKeyboard, gboolean bOSK)
{
- return g_slist_length (pKeyboard->pPrivate->lLayoutRec);
+ guint nLayouts = 0;
+
+ if (bOSK)
+ {
+ nLayouts = g_slist_length (pKeyboard->pPrivate->lLayoutRecOSK);
+ }
+ else
+ {
+ nLayouts = g_slist_length (pKeyboard->pPrivate->lLayoutRec);
+ }
+
+ return nLayouts;
}
-guint keyboard_GetLayoutIndex (Keyboard *pKeyboard)
+guint keyboard_GetLayoutIndex (Keyboard *pKeyboard, gboolean bOSK)
{
- return pKeyboard->pPrivate->nLayout;
+ if (bOSK)
+ {
+ return pKeyboard->pPrivate->nLayoutOSK;
+ }
+ else
+ {
+ return pKeyboard->pPrivate->nLayout;
+ }
}
-void keyboard_GetLayout(Keyboard *pKeyboard, gint nLayout, gchar **pLanguage, gchar **pDescription)
+void keyboard_GetLayout(Keyboard *pKeyboard, gboolean bOSK, gint nLayout, gchar **pLanguage, gchar **pDescription, gchar **pId)
{
- if (nLayout == -1)
+
+ GSList *lLayoutRec = NULL;
+
+ if (bOSK)
+ {
+ if (nLayout == -1)
+ {
+ nLayout = pKeyboard->pPrivate->nLayoutOSK;
+ }
+ lLayoutRec = pKeyboard->pPrivate->lLayoutRecOSK;
+ }
+ else
{
- nLayout = pKeyboard->pPrivate->nLayout;
+ if (nLayout == -1)
+ {
+ nLayout = pKeyboard->pPrivate->nLayout;
+ }
+ lLayoutRec = pKeyboard->pPrivate->lLayoutRec;
}
- gchar *sLayout = g_slist_nth_data (pKeyboard->pPrivate->lLayoutRec, nLayout);
+ gchar *sLayout = g_slist_nth_data (lLayoutRec, nLayout);
const Layout *pLayout;
g_hash_table_lookup_extended(pKeyboard->pPrivate->lLayouts, sLayout, NULL, (gpointer*)&pLayout);
@@ -199,9 +268,14 @@ void keyboard_GetLayout(Keyboard *pKeyboard, gint nLayout, gchar **pLanguage, gc
{
*pDescription = g_strdup(pLayout->sDescription);
}
+
+ if (pId != NULL)
+ {
+ *pId = g_strdup (sLayout);
+ }
}
-void keyboard_SetLayout(Keyboard *pKeyboard, gint nLayout)
+void keyboard_SetLayoutHardware(Keyboard *pKeyboard, gint nLayout)
{
if (isGreeter() == FALSE)
{
@@ -293,11 +367,103 @@ void keyboard_SetLayout(Keyboard *pKeyboard, gint nLayout)
}
}
+void keyboard_SetLayoutSoftware(Keyboard *pKeyboard, gint nLayout)
+{
+ if (isGreeter() == FALSE)
+ {
+ gchar *sId = g_slist_nth_data (pKeyboard->pPrivate->lLayoutRecOSK, nLayout);
+ guint nId = 0;
+ gchar *sLayoutOSK = NULL;
+
+ while (LOMIRI_TO_ISO[nId][0] != NULL)
+ {
+ gboolean bEqual = g_str_equal (LOMIRI_TO_ISO[nId][1], sId);
+
+ if (bEqual)
+ {
+ sLayoutOSK = LOMIRI_TO_ISO[nId][0];
+
+ break;
+ }
+
+ nId++;
+ }
+
+ if (!sLayoutOSK)
+ {
+ sLayoutOSK = sId;
+ }
+
+ guint nEnabledLayoutsOSK = g_slist_length (pKeyboard->pPrivate->lLayoutRecOSK);
+
+ GVariantBuilder cLayoutsOSKBuilder;
+ g_variant_builder_init (&cLayoutsOSKBuilder, G_VARIANT_TYPE ("as"));
+ if (sLayoutOSK)
+ {
+ g_variant_builder_add (&cLayoutsOSKBuilder, "s", sLayoutOSK);
+ }
+
+ for (guint nLayout = 0; nLayout < nEnabledLayoutsOSK; nLayout++)
+ {
+ gchar *sIdIso = g_slist_nth_data (pKeyboard->pPrivate->lLayoutRecOSK, nLayout);
+
+ nId = 0;
+ gchar *sIdLomiri = NULL;
+ while (LOMIRI_TO_ISO[nId][0] != NULL)
+ {
+ gboolean bEqual = g_str_equal (LOMIRI_TO_ISO[nId][1], sIdIso);
+
+ if (bEqual)
+ {
+ sIdLomiri = LOMIRI_TO_ISO[nId][0];
+
+ break;
+ }
+
+ nId++;
+ }
+ if (!sIdLomiri)
+ {
+ sIdLomiri = sIdIso;
+ }
+
+ if (strcmp(sIdLomiri, sLayoutOSK))
+ {
+ g_variant_builder_add (&cLayoutsOSKBuilder, "s", sIdLomiri);
+ }
+ }
+ GVariant *pEnabledLayoutsOSK = g_variant_builder_end (&cLayoutsOSKBuilder);
+
+ g_settings_set_string (pKeyboard->pPrivate->pMaliitSettings, "active-language", sLayoutOSK);
+ g_settings_set_value (pKeyboard->pPrivate->pMaliitSettings, "enabled-languages", pEnabledLayoutsOSK);
+ }
+ else
+ {
+ // TODO
+ }
+}
+
+void keyboard_SetLayout(Keyboard *pKeyboard, gint nLayout, gboolean bOSK)
+{
+ if (bOSK)
+ {
+ keyboard_SetLayoutSoftware(pKeyboard, nLayout);
+ }
+ else
+ {
+ keyboard_SetLayoutHardware(pKeyboard, nLayout);
+ }
+}
+
static void onDispose(GObject *pObject)
{
Keyboard *self = G_KEYBOARD(pObject);
g_signal_handlers_disconnect_by_data (self->pPrivate->pSettings, self);
g_clear_object (&self->pPrivate->pSettings);
+ g_signal_handlers_disconnect_by_data (self->pPrivate->pLomiriSettings, self);
+ g_clear_object (&self->pPrivate->pLomiriSettings);
+ g_signal_handlers_disconnect_by_data (self->pPrivate->pMaliitSettings, self);
+ g_clear_object (&self->pPrivate->pMaliitSettings);
if (self->pPrivate->lLayouts)
{
@@ -309,11 +475,31 @@ static void onDispose(GObject *pObject)
g_slist_free_full(self->pPrivate->lLayoutRec, g_free);
}
+ if (self->pPrivate->lLayoutRecOSK)
+ {
+ g_slist_free_full (self->pPrivate->lLayoutRecOSK, g_free);
+ }
+
if (self->pPrivate->lUsers)
{
g_slist_free(self->pPrivate->lUsers);
}
+ if (self->pPrivate->pChannel)
+ {
+ g_io_channel_unref (self->pPrivate->pChannel);
+ }
+
+ if (self->pPrivate->pMonitor)
+ {
+ udev_monitor_unref (self->pPrivate->pMonitor);
+ }
+
+ if (self->pPrivate->pUdev)
+ {
+ udev_unref (self->pPrivate->pUdev);
+ }
+
G_OBJECT_CLASS(keyboard_parent_class)->dispose(pObject);
}
@@ -371,10 +557,150 @@ static void onSourcesChanged (GSettings *pSettings, const gchar *sKey, gpointer
}
}
+static void onSoftwareKeyboardEnabled (GSettings *pSettings, const gchar *sKey, gpointer pData)
+{
+ Keyboard *self = G_KEYBOARD (pData);
+ self->pPrivate->bSoftwareKeyboard = g_settings_get_boolean (pSettings, "always-show-osk");
+ g_signal_emit (self, m_lSignals[CONFIG_CHANGED], 0);
+ g_signal_emit (self, m_lSignals[LAYOUT_CHANGED], 0);
+}
+
+static void onSoftwareLayoutChanged (GSettings *pSettings, const gchar *sKey, gpointer pData)
+{
+ Keyboard *pKeyboard = G_KEYBOARD (pData);
+ g_signal_emit (pKeyboard, m_lSignals[LAYOUT_CHANGED], 0);
+}
+
+static void onSoftwareLayoutsChanged (GSettings *pSettings, const gchar *sKey, gpointer pData)
+{
+ Keyboard *pKeyboard = G_KEYBOARD (pData);
+ gboolean bsignal = FALSE;
+
+ if (pKeyboard->pPrivate->lLayoutRecOSK)
+ {
+ g_slist_free_full (g_steal_pointer (&pKeyboard->pPrivate->lLayoutRecOSK), g_free);
+ bsignal = TRUE;
+ }
+
+ GStrv lLayouts = g_settings_get_strv (pSettings, "enabled-languages");
+ guint nLayouts = g_strv_length (lLayouts);
+
+ if (lLayouts)
+ {
+ for (guint nLayout = 0; nLayout < nLayouts; nLayout++)
+ {
+ guint nId = 0;
+ gchar *sLayout = NULL;
+
+ while (LOMIRI_TO_ISO[nId][0] != NULL)
+ {
+ gboolean bEqual = g_str_equal (LOMIRI_TO_ISO[nId][0], lLayouts[nLayout]);
+
+ if (bEqual)
+ {
+ sLayout = g_strdup (LOMIRI_TO_ISO[nId][1]);
+
+ break;
+ }
+
+ nId++;
+ }
+
+ if (!sLayout)
+ {
+ sLayout = g_strdup (lLayouts[nLayout]);
+ }
+
+ pKeyboard->pPrivate->lLayoutRecOSK = g_slist_append (pKeyboard->pPrivate->lLayoutRecOSK, sLayout);
+ }
+
+ g_strfreev (lLayouts);
+ }
+
+ if (bsignal)
+ {
+ g_signal_emit (pKeyboard, m_lSignals[CONFIG_CHANGED], 0);
+ g_signal_emit (pKeyboard, m_lSignals[LAYOUT_CHANGED], 0);
+ }
+}
+
+static bool udevDeviceIsHardwareKeyboard (struct udev_device *pDevice)
+{
+ const gchar *sValue = udev_device_get_property_value (pDevice, "ID_INPUT_KEYBOARD");
+ gint nCompared = g_strcmp0 (sValue, "1");
+
+ return nCompared == 0;
+}
+
+static gboolean udevHasHardwareKeyboard (struct udev *pUdev)
+{
+ struct udev_enumerate *pEnumerate = udev_enumerate_new (pUdev);
+ udev_enumerate_add_match_subsystem (pEnumerate, "input");
+ udev_enumerate_scan_devices (pEnumerate);
+ struct udev_list_entry *lEntries = udev_enumerate_get_list_entry (pEnumerate);
+ struct udev_list_entry *pEntry;
+ gboolean bFound = FALSE;
+
+ udev_list_entry_foreach (pEntry, lEntries)
+ {
+ const gchar *sPath = udev_list_entry_get_name (pEntry);
+ struct udev_device *pDevice = udev_device_new_from_syspath (pUdev, sPath);
+ gboolean bKeyboard = udevDeviceIsHardwareKeyboard (pDevice);
+
+ if (bKeyboard)
+ {
+ bFound = TRUE;
+ udev_device_unref (pDevice);
+
+ break;
+ }
+
+ udev_device_unref (pDevice);
+ }
+
+ udev_enumerate_unref (pEnumerate);
+
+ return bFound;
+}
+
+static gboolean onUdevEvent (GIOChannel *pChannel, GIOCondition nCondition, gpointer pData)
+{
+ Keyboard *self = G_KEYBOARD (pData);
+ struct udev_device *pDevice = udev_monitor_receive_device (self->pPrivate->pMonitor);
+
+ if (pDevice)
+ {
+ gboolean bKeyboard = udevDeviceIsHardwareKeyboard (pDevice);
+
+ if (bKeyboard)
+ {
+ struct udev *pUdev = udev_device_get_udev (pDevice);
+ self->pPrivate->bHardwareKeyboard = udevHasHardwareKeyboard (pUdev);
+ g_signal_emit (self, m_lSignals[CONFIG_CHANGED], 0);
+ g_signal_emit (self, m_lSignals[LAYOUT_CHANGED], 0);
+ }
+
+ udev_device_unref (pDevice);
+ }
+
+ return TRUE;
+}
+
+gboolean keyboard_hasHardwareKeyboard (Keyboard *self)
+{
+ return self->pPrivate->bHardwareKeyboard;
+}
+
+gboolean keyboard_hasSoftwareKeyboard (Keyboard *self)
+{
+ return self->pPrivate->bSoftwareKeyboard;
+}
+
static void keyboard_init(Keyboard *self)
{
self->pPrivate = keyboard_get_instance_private(self);
self->pPrivate->lLayoutRec = NULL;
+ self->pPrivate->lLayoutRecOSK = NULL;
self->pPrivate->lLayouts = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, freeLayout);
// Read all available layouts
@@ -422,6 +748,27 @@ static void keyboard_init(Keyboard *self)
rxkb_context_unref(pContext);
+ self->pPrivate->nLayoutOSK = 0;
+
+ // Lomiri-specific layouts
+ const gchar *LAYOUTS[][3] =
+ {
+ {"emoji", "emoji", "Emoji"},
+ {"Bn", "bn-avro", "Bangla (Avro)"},
+ {"Zn", "chewing", "Chinese (Chewing)"},
+ {"Zn", "pinyin", "Chinese (Pinyin)"}
+ };
+
+ for (guint nLayout = 0; nLayout < 3; nLayout++)
+ {
+ Layout *pLayout = g_slice_new0 (Layout);
+ pLayout->sId = g_strdup (LAYOUTS[nLayout][1]);
+ pLayout->sLanguage = g_strdup (LAYOUTS[nLayout][0]);
+ pLayout->sDescription = g_strdup (LAYOUTS[nLayout][2]);
+ g_hash_table_replace (self->pPrivate->lLayouts, pLayout->sId, pLayout);
+ }
+ //~Lomiri-specific layouts
+
if (isGreeter() == FALSE)
{
self->pPrivate->nLayout = 0;
@@ -492,4 +839,53 @@ static void keyboard_init(Keyboard *self)
g_signal_connect_object(pManager, "notify::is-loaded", G_CALLBACK(onManagerLoaded), self, G_CONNECT_SWAPPED);
}
}
+
+ // Watch for a hardware keyboard
+ self->pPrivate->pUdev = udev_new ();
+ self->pPrivate->pMonitor = udev_monitor_new_from_netlink (self->pPrivate->pUdev, "udev");
+ udev_monitor_filter_add_match_subsystem_devtype (self->pPrivate->pMonitor, "input", NULL);
+ udev_monitor_enable_receiving (self->pPrivate->pMonitor);
+ gint nFd = udev_monitor_get_fd (self->pPrivate->pMonitor);
+ self->pPrivate->bHardwareKeyboard = udevHasHardwareKeyboard (self->pPrivate->pUdev);
+ self->pPrivate->pChannel = g_io_channel_unix_new (nFd);
+ g_io_add_watch (self->pPrivate->pChannel, G_IO_IN, onUdevEvent, self);
+ //~Watch for a hardware keyboard
+
+ // Watch software keyboard
+ GSettingsSchemaSource *pSource = g_settings_schema_source_get_default ();
+ GSettingsSchema *pSchema = NULL;
+
+ if (pSource)
+ {
+ pSchema = g_settings_schema_source_lookup (pSource, "com.lomiri.Shell", FALSE);
+
+ if (pSchema)
+ {
+ g_settings_schema_unref (pSchema);
+ self->pPrivate->pLomiriSettings = g_settings_new ("com.lomiri.Shell");
+ g_signal_connect (self->pPrivate->pLomiriSettings, "changed::always-show-osk", G_CALLBACK (onSoftwareKeyboardEnabled), self);
+ onSoftwareKeyboardEnabled (self->pPrivate->pLomiriSettings, "always-show-osk", self);
+ }
+ else
+ {
+ g_error ("Panic: no com.lomiri.Shell schema found");
+ }
+
+ pSchema = g_settings_schema_source_lookup (pSource, "com.lomiri.keyboard.maliit", FALSE);
+
+ if (pSchema)
+ {
+ g_settings_schema_unref (pSchema);
+ self->pPrivate->pMaliitSettings = g_settings_new ("com.lomiri.keyboard.maliit");
+ g_signal_connect (self->pPrivate->pMaliitSettings, "changed::enabled-languages", G_CALLBACK (onSoftwareLayoutsChanged), self);
+ onSoftwareLayoutsChanged (self->pPrivate->pMaliitSettings, "enabled-languages", self);
+ g_signal_connect (self->pPrivate->pMaliitSettings, "changed::active-language", G_CALLBACK (onSoftwareLayoutChanged), self);
+ onSoftwareLayoutChanged (self->pPrivate->pMaliitSettings, "active-language", self);
+ }
+ else
+ {
+ g_error ("Panic: no com.lomiri.keyboard.maliit schema found");
+ }
+ }
+ //~Watch software keyboard
}
diff --git a/src/keyboard-x11.c b/src/keyboard-x11.c
index d7d482f5..75dabd6d 100644
--- a/src/keyboard-x11.c
+++ b/src/keyboard-x11.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2021-2024 Robert Tari <robert@tari.in>
+ * Copyright 2021-2025 Robert Tari <robert@tari.in>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
@@ -42,6 +42,7 @@ struct _KeyboardPrivate
GHashTable *lLayouts;
Display *pDisplay;
guint nLayout;
+ guint nLayoutOSK;
gint nXkbEventType;
XklConfigRec *pConfigRec;
GSList *lLayoutRec;
@@ -369,7 +370,7 @@ void keyboard_AddSource(Keyboard *pKeyboard)
}
}
-guint keyboard_GetNumLayouts(Keyboard *pKeyboard)
+guint keyboard_GetNumLayouts(Keyboard *pKeyboard, gboolean bOSK)
{
guint nLayouts = 0;
@@ -385,12 +386,12 @@ guint keyboard_GetNumLayouts(Keyboard *pKeyboard)
return nLayouts;
}
-guint keyboard_GetLayoutIndex (Keyboard *pKeyboard)
+guint keyboard_GetLayoutIndex (Keyboard *pKeyboard, gboolean bOSK)
{
return pKeyboard->pPrivate->nLayout;
}
-void keyboard_GetLayout(Keyboard *pKeyboard, gint nLayout, gchar **pLanguage, gchar **pDescription)
+void keyboard_GetLayout(Keyboard *pKeyboard, gboolean bOSK, gint nLayout, gchar **pLanguage, gchar **pDescription, gchar **pId)
{
if (nLayout == -1)
{
@@ -432,10 +433,17 @@ void keyboard_GetLayout(Keyboard *pKeyboard, gint nLayout, gchar **pLanguage, gc
*pDescription = g_strdup(pLayout->sDescription);
}
- g_free(sId);
+ if (pId != NULL)
+ {
+ *pId = sId;
+ }
+ else
+ {
+ g_free(sId);
+ }
}
-void keyboard_SetLayout(Keyboard *pKeyboard, gint nLayout)
+void keyboard_SetLayout(Keyboard *pKeyboard, gint nLayout, gboolean bOSK)
{
if (isGreeter() == FALSE)
{
@@ -565,6 +573,16 @@ static void onUserChanged (GDBusConnection *pConnection, const gchar *sSender, c
}
}
+gboolean keyboard_hasHardwareKeyboard (Keyboard *self)
+{
+ return TRUE;
+}
+
+gboolean keyboard_hasSoftwareKeyboard (Keyboard *self)
+{
+ return FALSE;
+}
+
static void keyboard_init(Keyboard *self)
{
self->pPrivate = keyboard_get_instance_private(self);
diff --git a/src/keyboard.h b/src/keyboard.h
index 39f822cd..206c4bf3 100644
--- a/src/keyboard.h
+++ b/src/keyboard.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2021-2023 Robert Tari <robert@tari.in>
+ * Copyright 2021-2025 Robert Tari <robert@tari.in>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
@@ -46,10 +46,12 @@ struct _KeyboardClass
GType keyboard_get_type(void);
Keyboard* keyboard_new();
void keyboard_AddSource(Keyboard *pKeyboard);
-guint keyboard_GetNumLayouts(Keyboard *pKeyboard);
-guint keyboard_GetLayoutIndex (Keyboard *pKeyboard);
-void keyboard_GetLayout(Keyboard *pKeyboard, gint nLayout, gchar **pLanguage, gchar **pDescription);
-void keyboard_SetLayout(Keyboard *pKeyboard, gint nLayout);
+guint keyboard_GetNumLayouts(Keyboard *pKeyboard, gboolean bOSK);
+guint keyboard_GetLayoutIndex (Keyboard *pKeyboard, gboolean bOSK);
+void keyboard_GetLayout(Keyboard *pKeyboard, gboolean bOSK, gint nLayout, gchar **pLanguage, gchar **pDescription, gchar **pId);
+void keyboard_SetLayout(Keyboard *pKeyboard, gint nLayout, gboolean bOSK);
+gboolean keyboard_hasHardwareKeyboard(Keyboard *pKeyboard);
+gboolean keyboard_hasSoftwareKeyboard(Keyboard *pKeyboard);
G_END_DECLS
diff --git a/src/service.c b/src/service.c
index 31f6ca3b..123308c9 100644
--- a/src/service.c
+++ b/src/service.c
@@ -25,14 +25,19 @@
#define ICON_DEFAULT "input-keyboard"
+#define HWKBD FALSE
+#define OSK TRUE
+
static guint m_nSignal = 0;
static void *m_pLibHandle = NULL;
static Keyboard* (*m_fnKeyboardNew)();
static void (*m_fnKeyboardAddSource)(Keyboard *pKeyboard);
-static guint (*m_fnKeyboardGetNumLayouts)(Keyboard *pKeyboard);
+static guint (*m_fnKeyboardGetNumLayouts)(Keyboard *pKeyboard, gboolean bOSK);
static guint (*m_fnKeyboardGetLayoutIndex)(Keyboard *pKeyboard);
-static void (*m_fnKeyboardGetLayout)(Keyboard *pKeyboard, gint nLayout, gchar **pLanguage, gchar **pDescription);
-static void (*m_fnKeyboardSetLayout)(Keyboard *pKeyboard, gint nLayout);
+static void (*m_fnKeyboardGetLayout)(Keyboard *pKeyboard, gboolean bOSK, gint nLayout, gchar **pLanguage, gchar **pDescription, gchar **pId);
+static void (*m_fnKeyboardSetLayout)(Keyboard *pKeyboard, gint nLayout, gboolean bOSK);
+static gboolean (*m_fnKeyboardHasHardwareKeyboard)(Keyboard *pKeyboard);
+static gboolean (*m_fnKeyboardHasSoftwareKeyboard)(Keyboard *pKeyboard);
enum
{
@@ -77,6 +82,7 @@ struct _IndicatorKeyboardServicePrivate
GSimpleAction *pSettingsAction;
GSimpleAction *pDisplayAction;
GSimpleAction *pLayoutAction;
+ GSimpleAction *pOSKLayoutAction;
GMenu *pLayoutSection;
Keyboard *pKeyboard;
GSettings *pSettings;
@@ -120,8 +126,9 @@ static GVariant* createHeaderState(IndicatorKeyboardService *self, int nProfile)
}
else
{
+ gboolean bHardwareKeyboard = m_fnKeyboardHasHardwareKeyboard (self->pPrivate->pKeyboard);
gchar *sLanguage;
- m_fnKeyboardGetLayout(self->pPrivate->pKeyboard, -1, &sLanguage, NULL);
+ m_fnKeyboardGetLayout(self->pPrivate->pKeyboard, self->pPrivate->bLomiri && !bHardwareKeyboard, -1, &sLanguage, NULL, NULL);
gchar *sIcon = g_strconcat("ayatana-indicator-keyboard-", sLanguage, NULL);
g_free(sLanguage);
@@ -148,20 +155,67 @@ static GVariant* createHeaderState(IndicatorKeyboardService *self, int nProfile)
return g_variant_builder_end(&cBuilder);
}
-static GMenuModel* createLayoutSection(IndicatorKeyboardService *self)
+static GMenuModel* createLayoutSection(IndicatorKeyboardService *self, gboolean bOSK)
{
self->pPrivate->pLayoutSection = g_menu_new();
+ gboolean bCreate = TRUE;
- guint nLayouts = m_fnKeyboardGetNumLayouts(self->pPrivate->pKeyboard);
+ if (self->pPrivate->bLomiri)
+ {
+ if (!bOSK)
+ {
+ gboolean bHardwareKeyboard = m_fnKeyboardHasHardwareKeyboard (self->pPrivate->pKeyboard);
+
+ if (bHardwareKeyboard)
+ {
+ g_menu_append (self->pPrivate->pLayoutSection, _("External Keyboard"), NULL);
+ }
+ else
+ {
+ bCreate = FALSE;
+ }
+ }
+ else if (bOSK)
+ {
+ gboolean bSoftwareKeyboard = m_fnKeyboardHasSoftwareKeyboard (self->pPrivate->pKeyboard);
+ g_menu_append (self->pPrivate->pLayoutSection, _("On-Screen Keyboard"), NULL);
+
+ if (!bSoftwareKeyboard)
+ {
+ bCreate = FALSE;
+ }
+ }
+ }
+ else if (bOSK)
+ {
+ bCreate = FALSE;
+ }
+ if (!bCreate)
+ {
+ return G_MENU_MODEL(self->pPrivate->pLayoutSection);
+ }
+
+ guint nLayouts = m_fnKeyboardGetNumLayouts(self->pPrivate->pKeyboard, bOSK);
for (guint nLayout = 0; nLayout < nLayouts; nLayout++)
{
gchar *sLanguage;
gchar *sDescription;
- m_fnKeyboardGetLayout(self->pPrivate->pKeyboard, nLayout, &sLanguage, &sDescription);
+ m_fnKeyboardGetLayout(self->pPrivate->pKeyboard, bOSK, nLayout, &sLanguage, &sDescription, NULL);
GMenuItem *pItem = g_menu_item_new(sDescription, NULL);
g_free(sDescription);
- g_menu_item_set_action_and_target_value(pItem, "indicator.layout", g_variant_new_byte(nLayout));
+ gchar *sAction = NULL;
+
+ if (bOSK)
+ {
+ sAction = "indicator.osklayout";
+ }
+ else
+ {
+ sAction = "indicator.layout";
+ }
+
+ g_menu_item_set_action_and_target_value(pItem, sAction, g_variant_new_byte(nLayout));
g_menu_item_set_attribute_value(pItem, "x-ayatana-layout", g_variant_new_byte(nLayout));
gchar *sIcon = g_strconcat("ayatana-indicator-keyboard-", sLanguage, NULL);
g_free(sLanguage);
@@ -184,11 +238,12 @@ static GMenuModel* createLayoutSection(IndicatorKeyboardService *self)
return G_MENU_MODEL(self->pPrivate->pLayoutSection);
}
-static GMenuModel* createSettingsSection(IndicatorKeyboardService *self)
+static GMenuModel* createSettingsSection(IndicatorKeyboardService *self, gboolean bOSK)
{
GMenu * pMenu = g_menu_new();
+ gboolean bUbuntuTouch = ayatana_common_utils_is_ubuntutouch ();
- if (self->pPrivate->bLomiri && (!ayatana_common_utils_is_ubuntutouch()))
+ if (self->pPrivate->bLomiri && bOSK && !bUbuntuTouch)
{
GMenuItem *pItem = g_menu_item_new (_("Always show OSK"), "indicator.osk(true)");
g_menu_item_set_attribute (pItem, "x-ayatana-type", "s", "org.ayatana.indicator.switch");
@@ -196,7 +251,33 @@ static GMenuModel* createSettingsSection(IndicatorKeyboardService *self)
g_object_unref (pItem);
}
- g_menu_append(pMenu, _("Keyboard Settings…"), "indicator.settings");
+ gchar *sAction = NULL;
+
+ if (self->pPrivate->bLomiri)
+ {
+ if (!bOSK)
+ {
+ gboolean bHardwareKeyboard = m_fnKeyboardHasHardwareKeyboard (self->pPrivate->pKeyboard);
+
+ if (bHardwareKeyboard)
+ {
+ sAction = "indicator.settings";
+ }
+ }
+ else if (bOSK)
+ {
+ sAction = "indicator.osksettings";
+ }
+ }
+ else if (!bOSK)
+ {
+ sAction = "indicator.settings";
+ }
+
+ if (sAction)
+ {
+ g_menu_append(pMenu, _("Keyboard Settings…"), sAction);
+ }
return G_MENU_MODEL(pMenu);
}
@@ -204,7 +285,22 @@ static GMenuModel* createSettingsSection(IndicatorKeyboardService *self)
static GMenuModel* createDisplaySection (IndicatorKeyboardService *self)
{
GMenu * pMenu = g_menu_new ();
- g_menu_append (pMenu, _("Show Current Layout"), "indicator.display");
+ gboolean bDisplay = TRUE;
+
+ if (self->pPrivate->bLomiri)
+ {
+ gboolean bHardwareKeyboard = m_fnKeyboardHasHardwareKeyboard (self->pPrivate->pKeyboard);
+
+ if (!bHardwareKeyboard)
+ {
+ bDisplay = FALSE;
+ }
+ }
+
+ if (bDisplay)
+ {
+ g_menu_append (pMenu, _("Show Current Layout"), "indicator.display");
+ }
return G_MENU_MODEL (pMenu);
}
@@ -236,9 +332,12 @@ static void rebuildNow(IndicatorKeyboardService *self, guint nSections)
if (nSections & SECTION_LAYOUTS)
{
- rebuildSection(pInfoDesktop->pSubmenu, 0, createLayoutSection(self));
- rebuildSection(pInfoPhone->pSubmenu, 0, createLayoutSection(self));
- rebuildSection(pInfoGreeter->pSubmenu, 0, createLayoutSection(self));
+ rebuildSection(pInfoDesktop->pSubmenu, 0, createLayoutSection(self, HWKBD));
+ rebuildSection(pInfoDesktop->pSubmenu, 3, createLayoutSection(self, OSK));
+ rebuildSection(pInfoPhone->pSubmenu, 0, createLayoutSection(self, HWKBD));
+ rebuildSection(pInfoPhone->pSubmenu, 2, createLayoutSection(self, OSK));
+ rebuildSection(pInfoGreeter->pSubmenu, 0, createLayoutSection(self, HWKBD));
+ rebuildSection(pInfoGreeter->pSubmenu, 1, createLayoutSection(self, OSK));
}
if (nSections & SECTION_DISPLAY)
@@ -248,8 +347,10 @@ static void rebuildNow(IndicatorKeyboardService *self, guint nSections)
if (nSections & SECTION_SETTINGS)
{
- rebuildSection(pInfoDesktop->pSubmenu, 2, createSettingsSection(self));
- rebuildSection(pInfoPhone->pSubmenu, 2, createSettingsSection(self));
+ rebuildSection(pInfoDesktop->pSubmenu, 2, createSettingsSection(self, HWKBD));
+ rebuildSection(pInfoDesktop->pSubmenu, 4, createSettingsSection(self, OSK));
+ rebuildSection(pInfoPhone->pSubmenu, 1, createSettingsSection(self, HWKBD));
+ rebuildSection(pInfoPhone->pSubmenu, 3, createSettingsSection(self, OSK));
}
}
@@ -267,18 +368,23 @@ static void createMenu(IndicatorKeyboardService *self, int nProfile)
// Build the sections
if (nProfile == PROFILE_PHONE)
{
- lSections[nSection++] = createLayoutSection(self);
- lSections[nSection++] = createSettingsSection(self);
+ lSections[nSection++] = createLayoutSection(self, HWKBD);
+ lSections[nSection++] = createSettingsSection(self, HWKBD);
+ lSections[nSection++] = createLayoutSection(self, OSK);
+ lSections[nSection++] = createSettingsSection(self, OSK);
}
else if (nProfile == PROFILE_DESKTOP)
{
- lSections[nSection++] = createLayoutSection(self);
+ lSections[nSection++] = createLayoutSection(self, HWKBD);
lSections[nSection++] = createDisplaySection(self);
- lSections[nSection++] = createSettingsSection(self);
+ lSections[nSection++] = createSettingsSection(self, HWKBD);
+ lSections[nSection++] = createLayoutSection(self, OSK);
+ lSections[nSection++] = createSettingsSection(self, OSK);
}
else if (nProfile == PROFILE_GREETER)
{
- lSections[nSection++] = createLayoutSection(self);
+ lSections[nSection++] = createLayoutSection(self, HWKBD);
+ lSections[nSection++] = createLayoutSection(self, OSK);
}
// Add sections to the submenu
@@ -323,7 +429,14 @@ static void onLayoutSelected(GSimpleAction *pAction, GVariant *pVariant, gpointe
{
IndicatorKeyboardService *self = INDICATOR_KEYBOARD_SERVICE(pData);
const guint8 nLayout = g_variant_get_byte(pVariant);
- m_fnKeyboardSetLayout(self->pPrivate->pKeyboard, nLayout);
+ m_fnKeyboardSetLayout(self->pPrivate->pKeyboard, nLayout, HWKBD);
+}
+
+static void onOSKLayoutSelected (GSimpleAction *pAction, GVariant *pVariant, gpointer pData)
+{
+ IndicatorKeyboardService *self = INDICATOR_KEYBOARD_SERVICE (pData);
+ const guint8 nLayout = g_variant_get_byte (pVariant);
+ m_fnKeyboardSetLayout (self->pPrivate->pKeyboard, nLayout, OSK);
}
static void onSettings(GSimpleAction *pAction, GVariant *pVariant, gpointer pData)
@@ -340,22 +453,37 @@ static void onSettings(GSimpleAction *pAction, GVariant *pVariant, gpointer pDat
}
}
+static void onOSKSettings(GSimpleAction *pAction, GVariant *pVariant, gpointer pData)
+{
+ ayatana_common_utils_open_url ("settings:///system/sw-keyboard-layouts");
+}
+
static void onDisplay (GSimpleAction *pAction, GVariant *pVariant, gpointer pData)
{
IndicatorKeyboardService *self = INDICATOR_KEYBOARD_SERVICE (pData);
guint nLayout = m_fnKeyboardGetLayoutIndex (self->pPrivate->pKeyboard);
gchar *sProgram = NULL;
+ gchar *sArgs = NULL;
+ gboolean bMate = ayatana_common_utils_is_mate ();
+ gboolean bLomiri = ayatana_common_utils_is_lomiri ();
- if (ayatana_common_utils_is_mate ())
+ if (bMate)
{
sProgram = "matekbd-keyboard-display";
+ sArgs = g_strdup_printf ("-g %i", nLayout + 1);
+ }
+ else if (bLomiri)
+ {
+
+ sProgram = "tecla";
+ m_fnKeyboardGetLayout (self->pPrivate->pKeyboard, HWKBD, -1, NULL, NULL, &sArgs);
}
else
{
sProgram = "gkbd-keyboard-display";
+ sArgs = g_strdup_printf ("-g %i", nLayout + 1);
}
- gchar *sArgs = g_strdup_printf ("-g %i", nLayout + 1);
ayatana_common_utils_execute_command_warn (sProgram, sArgs);
g_free (sArgs);
}
@@ -393,6 +521,14 @@ static void initActions(IndicatorKeyboardService *self)
self->pPrivate->pLayoutAction = pAction;
g_signal_connect(pAction, "activate", G_CALLBACK(onLayoutSelected), self);
+ if (self->pPrivate->bLomiri)
+ {
+ pAction = g_simple_action_new("osklayout", G_VARIANT_TYPE_BYTE);
+ g_action_map_add_action(G_ACTION_MAP(self->pPrivate->pActionGroup), G_ACTION(pAction));
+ self->pPrivate->pOSKLayoutAction = pAction;
+ g_signal_connect(pAction, "activate", G_CALLBACK(onOSKLayoutSelected), self);
+ }
+
if (self->pPrivate->bLomiri && (!ayatana_common_utils_is_ubuntutouch()))
{
gboolean bOsk = g_settings_get_boolean (self->pPrivate->pLomiriSettings, "always-show-osk");
@@ -408,6 +544,14 @@ static void initActions(IndicatorKeyboardService *self)
self->pPrivate->pSettingsAction = pAction;
g_signal_connect(pAction, "activate", G_CALLBACK(onSettings), self);
+ if (self->pPrivate->bLomiri)
+ {
+ pAction = g_simple_action_new ("osksettings", NULL);
+ g_action_map_add_action(G_ACTION_MAP (self->pPrivate->pActionGroup), G_ACTION (pAction));
+ self->pPrivate->pSettingsAction = pAction;
+ g_signal_connect (pAction, "activate", G_CALLBACK (onOSKSettings), self);
+ }
+
pAction = g_simple_action_new ("display", NULL);
g_action_map_add_action (G_ACTION_MAP (self->pPrivate->pActionGroup), G_ACTION (pAction));
self->pPrivate->pDisplayAction = pAction;
@@ -524,6 +668,7 @@ static void onDispose(GObject *pObject)
g_clear_object (&self->pPrivate->pSettingsAction);
g_clear_object (&self->pPrivate->pDisplayAction);
g_clear_object (&self->pPrivate->pLayoutAction);
+ g_clear_object (&self->pPrivate->pOSKLayoutAction);
for (int nProfile = 0; nProfile < N_PROFILES; ++nProfile)
{
@@ -579,6 +724,8 @@ static void indicator_keyboard_service_init(IndicatorKeyboardService *self)
m_fnKeyboardGetLayoutIndex = dlsym(m_pLibHandle, "keyboard_GetLayoutIndex");
m_fnKeyboardGetLayout = dlsym(m_pLibHandle, "keyboard_GetLayout");
m_fnKeyboardSetLayout = dlsym(m_pLibHandle, "keyboard_SetLayout");
+ m_fnKeyboardHasHardwareKeyboard = dlsym(m_pLibHandle, "keyboard_hasHardwareKeyboard");
+ m_fnKeyboardHasSoftwareKeyboard = dlsym(m_pLibHandle, "keyboard_hasSoftwareKeyboard");
self->pPrivate = indicator_keyboard_service_get_instance_private(self);
self->pPrivate->bLomiri = bLomiri;
self->pPrivate->pCancellable = g_cancellable_new();