Как добавить апплет состояния модификатора клавиатуры на панель Unity?
Я пользователь KDE и думаю о переходе на Unity. Из-за ручного отключения я использую липкие клавиши, а в KDE на системной панели есть апплет, который показывает, какие клавиши-модификаторы активны. Я помню, что у Gnome была и эта функция, как и у Windows и OS X.
Как можно добавить апплет состояния модификатора клавиатуры на панель в Unity?
Уточнение: я уже включил липкие клавиши. Я спрашиваю, как добавить апплет, который указывает состояние клавиш-модификаторов. Этот индикатор показывает, когда нажата клавиша Shift, когда нажата клавиша Alt, когда нажата клавиша Tux и когда нажата клавиша Ctrl. Этот апплет существует во всех основных средах рабочего стола (KDE, Windows, Mac OSX и Gnome). Это необходимо для доступности рабочего стола.
Вот изображение апплета состояния модификатора клавиатуры, рядом с апплетом индикатора раскладки клавиатуры. Представленные модификаторы слева направо Shift
, Ctrl
, Alt
, I-dont-know-this-one
, Tux/Win
, NumLock
, а также CapsLock
, Видно, что клавиша NumLock активна.
3 ответа
Это выдающаяся проблема в Unity:
- lp # 773078 Должен каким-то образом отображать статус StickyKeys (a11y)
- lp # 1306584 В Unity нет апплета состояния клавиатуры (спасибо @dotancohen)
Код ниже был обновлен, теперь он может использовать иконки для отображения состояния. Но иногда это может замедлиться, так как мне приходится обновлять файл значков на жестком диске, а затем снова его загружать. (См. Примечания об этой проблеме / ограничении в libappindicator
)
Хорошо упакованный релиз был сделан доступным на webupd8 ppa (спасибо Алине Андрей / Андрей /)
sudo add-apt-repository ppa:nilarimogard/webupd8
sudo apt-get update
sudo apt-get install indicator-xkbmod
Ссылка: Индикатор состояния модификаторов клавиатуры Для Ubuntu: Индикатор Xkbmod
Оригинальный ответ:
Это не является каноническим ответом на вопрос. Это можно считать обходным решением. Прыжки кто-то пишет сложные решения для этого.
Это простой прототип индикатора модификаторов клавиатуры для Unity.
Изображение начинается слева: иконка, Shift, закрытые буквы, Ctrl, Alt, Super, Locked AltGr (маленький кружок для обозначения заблокированного состояния)
Исходный файл unity-xkbmod.c
:
/*
* unity-xkbmod.c
*
* Copyright 2014 Sneetsher <sneetsher@localhost>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*
*/
#include <string.h>
#include <X11/XKBlib.h>
#include <glib/gprintf.h>
#include <gtk/gtk.h>
#include <libappindicator/app-indicator.h>
//callback data structure
typedef struct _AppData {
Display *_display;
int *_deviceId;
AppIndicator *indicator;
} AppData;
//menu ui
static GtkActionEntry entries[] = {
{ "Quit", "application-exit", "_Quit", "<control>Q",
"Exit the application", G_CALLBACK (gtk_main_quit) },
};
static guint n_entries = G_N_ELEMENTS (entries);
static const gchar *ui_info =
"<ui>"
" <popup name='IndicatorPopup'>"
" <menuitem action='Quit' />"
" </popup>"
"</ui>";
//callback function, get xkb state, update indicator label (icon have limitation)
static gboolean update_xkb_state (gpointer data)
{
//get xkb state
XkbStateRec xkbState;
XkbGetState(((AppData*) data)->_display, *(((AppData*) data)->_deviceId), &xkbState);
//construct label
GString *label = g_string_new("");
register int i;
unsigned bit;
//loop taken from xkbwatch source
for (i = XkbNumModifiers - 1, bit = 0x80; i >= 0; i--, bit >>= 1)
{
//printf("base%d %s ", i, (xkbState.base_mods & bit) ? "on " : "off");
//printf("latched%d %s ", i, (xkbState.latched_mods & bit) ? "on " : "off");
//printf("locked%d %s ", i, (xkbState.locked_mods & bit) ? "on " : "off");
//printf("effective%d %s ", i, (xkbState.mods & bit) ? "on " : "off");
//printf("compat%d %s\n", i, (xkbState.compat_state & bit) ? "on " : "off");
//todo: change constant with xkb modifier constant (defined in the headers)
// show effective modifier stat
switch (i)
{
case 7:
g_string_prepend (label, ((xkbState.mods & bit) ? "⎇" : ""));
break;
case 6:
g_string_prepend (label, ((xkbState.mods & bit) ? "⌘" : ""));
break;
case 5:
g_string_prepend (label, ((xkbState.mods & bit) ? "5" : ""));
break;
case 4:
g_string_prepend (label, ((xkbState.mods & bit) ? "①" : ""));
break;
case 3:
g_string_prepend (label, ((xkbState.mods & bit) ? "⌥" : ""));
break;
case 2:
g_string_prepend (label, ((xkbState.mods & bit) ? "⋀" : ""));
break;
case 1:
g_string_prepend (label, ((xkbState.mods & bit) ? "⇬" : ""));
break;
case 0:
g_string_prepend (label, ((xkbState.mods & bit) ? "⇧" : ""));
break;
default:
break;
};
// show if modifier is locked
g_string_prepend (label, ((xkbState.locked_mods & bit) ? " ˳" : " "));
}
//g_string_prepend (label, "");
app_indicator_set_label (((AppData*) data)->indicator, label->str, NULL);
//g_free(label);
return TRUE;
}
int main (int argc, char **argv)
{
AppData appdata;
Display *_display;
int _deviceId;
char* displayName = strdup("");
int eventCode;
int errorReturn;
int major = XkbMajorVersion;
int minor = XkbMinorVersion;;
int reasonReturn;
AppIndicator *indicator;
GtkWidget *indicator_menu;
GtkUIManager *uim;
GtkActionGroup *action_group;
GError *error = NULL;
gtk_init (&argc, &argv);
XkbIgnoreExtension(False);
g_printf("Xkb client lib ver: %d.%d\n" , major , minor );
_display = XkbOpenDisplay(displayName, &eventCode, &errorReturn,
&major, &minor, &reasonReturn);
g_printf("Xkb server lib ver: %d.%d\n" , major , minor );
if (reasonReturn != XkbOD_Success)
{
g_printf("Unable to open display!\n");
return 1;
}
XkbDescRec* kbdDescPtr = XkbAllocKeyboard();
if (kbdDescPtr == NULL)
{
g_printf ("Failed to get keyboard description.\n");
return 2;
}
kbdDescPtr->dpy = _display;
_deviceId = kbdDescPtr->device_spec;
/*
//no need for event listener, used gtk_timeout timer
XkbSelectEventDetails(_display, XkbUseCoreKbd, XkbStateNotify,
XkbAllStateComponentsMask, XkbGroupStateMask);
*/
action_group = gtk_action_group_new ("AppActions");
gtk_action_group_add_actions (action_group, entries, n_entries, NULL);
indicator = app_indicator_new_with_path (
"Simple XKB Modifier Indicator",
"icon",
APP_INDICATOR_CATEGORY_HARDWARE,
g_get_current_dir());
uim = gtk_ui_manager_new ();
gtk_ui_manager_insert_action_group (uim, action_group, 0);
if (!gtk_ui_manager_add_ui_from_string (uim, ui_info, -1, &error))
{
g_printf ("Failed to build menus: %s\n", error->message);
g_error_free (error);
error = NULL;
return 3;
}
indicator_menu = gtk_ui_manager_get_widget (uim, "/ui/IndicatorPopup");
app_indicator_set_menu (indicator, GTK_MENU (indicator_menu));
app_indicator_set_status (indicator, APP_INDICATOR_STATUS_ACTIVE);
//app_indicator_set_label (indicator, " ⇧ ⋀ ⌥ ⎇ ⌘ ", NULL);
//symbols: shift U21E7 ctrl U22C0 alt/altgr U2325 U2387 cmd U2318
//from font: DejaVu Sans
appdata._display = _display;
appdata._deviceId = &_deviceId;
appdata.indicator = indicator;
gtk_timeout_add (120, (GtkFunction) update_xkb_state, &appdata);
//nice for realtime tasks, to replace gtk_timeout
//gtk_idle_add ((GtkFunction) idle_func, &appdata);
gtk_main ();
XCloseDisplay (_display);
return 0;
}
Установка необходимых заголовков / библиотек: (Не уверен, что я что-то пропустил)
sudo apt-get install libx11-dev libappindicator-dev libgtk2.0-dev
Компиляция:
gcc -Wall unity-xkbmod.c -o unity-xkbmod `pkg-config --cflags --libs appindicator-0.1` -lX11
Бежать:
./unity-xkbmod
Замечания:
libappindicator
Используемые для индикаторов Unity отсутствуют важные функции, упрощающие портирование других индикаторов рабочего стола. См. Ошибка #812067 Необходим API: поддержка настройки иконки pixbufБез этой функции, скажем, нам нужны (Shift, Ctrl, Alt, AltGr, Super) с активными липкими клавишами; у нас есть 3 основных статуса для каждого (Выкл., Вкл / Защелка, Заблокировано). Таким образом, 3^5 комбинированных иконок должны быть сгенерированы. (Где нормальный случай только 3х5 одиночных значков)
Поэтому я использовал индикаторную метку с символами из шрифта DejaVu Sans.
Чтобы поместить значок, поместите его в ту же папку и назовите его
icon.*
, Принятые форматы: PNG, SVG, ICO, XPM...Если вам не нравится какой-либо значок, просто создайте изображение размером 1x1 px.
Рекомендации:
- Расширение клавиатуры X
- Индикаторы панели приложений
- Источник
xkbwatch
&plasma-widget-kbstate
Другое решение, которое не является идеальным, но некоторые могут найти его полезным, так как возможно иметь полную функциональность, как в KDE, например, активировать мод одним кликом.
устанавливать
kbstate
апплетsudo apt-get install plasma-widget-kbstate kde-workspace-bin
Запустите это в
plasma-windowed
игрокОбычное окно
plasma-windowed kbstate
Окно без границ
plasma-windowed --noborder kbstate
У меня не было много времени, чтобы играть, но wmctrl
может помочь расположить, изменить размер и сделать его сверху при запуске.
Ссылка: Какая команда для запуска плазмоида kde и меню кикстарта
Я выполнил поиск монитора липких ключей Ubuntu и нашел кое-что полезное здесь: http://code.google.com/p/key-mon/
Попробуйте запустить
key-mon --sticky
Поддержка липких ключей.
Ссылка: http://code.google.com/p/key-mon/
Обратите внимание, что версия, доступная через центр программного обеспечения, - 1.6-0ubuntu1. Выпущен в июне 2011 года, который не поддерживает параметр --sticky. Если индикатор выглядит точно так же, как указано выше, у вас есть более старая версия. Попробуйте последнюю версию по адресу http://code.google.com/p/key-mon/ написания статьи она выпущена keymon_1.17-1_all.deb 229 КБ. 3 января 2014 года. Поддержка --sticky switch проверена и подтверждена.