Як додати аплет стану модифікатора клавіатури на панель Unity?


18

Я користувач 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 активна.

введіть тут опис зображення


Errr ... Здається, великий розрив, коли справа доходить до цього ... Існує річ, що подається, коли натискається клавіша модифікатора.
Вільф

@wilf Якщо я не помиляюся, в Unity є значок Доступності (такий же, як Gnome 3), але не "зайвий" значок, щоб повідомити користувача про стан.
Брайам

4
@Takkat: Дякую за пропозицію. indicator-keylockтільки відображає стан тих ключів , які традиційно мають індикатори стану на самій клавіатурі: CapsLock, ScrollLock, NumLock. Мені потрібен індикатор , який показує стан стандартних клавіш - модифікаторів: Shift, Ctrl, Tux, Alt. Усі основні настільні комп’ютери (KDE, Windows, Mac OSX) мають цей індексний аплет.
dotancohen

1
Я вважаю, що назва пакету інструменту KDE, на який ви також посилаєтесь, plasma-widget-kbstateі швидкий пошук у центрі програмного забезпечення насправді не прислуховується до еквівалентних результатів
Daniel W.

2
@shengy: Я використовую плазмоїд KB State. Якщо ви перебуваєте на Kubuntu, то встановіть його sudo apt-get install plasma-widget-kbstate.
dotancohen

Відповіді:


7

Це вирішення проблеми Unity:

Код нижче оновлено, тепер він може використовувати піктограми для показу стану. Але це може початися повільно, коли мені доведеться оновити файл значків на жорсткому диску, а потім перезавантажити його знову. (Див. Примітки щодо цієї проблеми / обмеження в libappindicator)

Добре упакований реліз був доступний на веб-сайті 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, заблокований AltGr (Мале коло, щоб вказати на стан заблокованого)

скріншот прототипу юнит-xkbmod

Вихідний файл 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;
}
  1. Встановлення потрібних заголовків / libs: (Не впевнений, якщо я пропускаю)

    sudo apt-get install libx11-dev libappindicator-dev libgtk2.0-dev
    
  2. Складання:

    gcc -Wall unity-xkbmod.c -o unity-xkbmod `pkg-config --cflags --libs appindicator-0.1` -lX11
    
  3. Виконати:

    ./unity-xkbmod
    

Примітка:

  • libappindicatorДля індикаторів Unity немає важливої ​​функції, яка полегшує порти інших індикаторів настільних ПК. Див. Помилку № 812067 API: підтримка налаштування піктограми pixbuf

    Без цієї функції, скажімо, нам потрібні (Shift, Ctrl, Alt, AltGr, Super) із активними липкими клавішами; у нас є 3 основних статусу для кожного (Off, On / Latched, Locked). Отже, слід створити 3 ^ 5 комбінованих піктограм. (У звичайному випадку лише 3x5 одиночних значків)

    Ось чому я використовував мітку індикатора із символами шрифту DejaVu Sans .

  • Щоб помістити піктограму, помістіть її в ту саму папку та назвіть її icon.*. Прийняті формати: png, svg, ico, xpm ...

    Якщо вам не подобається жодна піктограма, просто створіть натомість зображення 1x1 пікселя.

Список літератури:


Приємно, дякую! Я спробую це повернутись до вас. Чудова робота, Sneetsher!
dotancohen

Щоб ти снайпер!
dotancohen

так, дякую @dotancohen. Так, принаймні, ви можете використовувати Unity, можливо, це некрасиво без значків фіксованого положення?
user.dz

1
Я не проти некрасивого, ви повинні побачити мене! Я вже згадував цю проблему в багтейкері Ubuntu .
dotancohen

1
Sneetsher, я хотів ще раз подякувати вам. Зараз я перейшов до Єдності, і цей крок був би неможливий без цього приголомшливого застосування. Я також досить багато навчився з коду. Дякую!
dotancohen

2

Ще одне рішення, яке не є ідеальним, але деякі можуть вважати його корисним, оскільки можливо мати повний функціонал, як у KDE, як активація мода клацанням.

  1. встановити kbstateаплет

    sudo apt-get install plasma-widget-kbstate kde-workspace-bin
    
  2. Запустити його в plasma-windowedпрогравачі

    • Регулярне вікно

      plasma-windowed kbstate
      

      скріншот плазми-віджета-kbstate в Xubuntu

    • Безмежне вікно

      plasma-windowed --noborder kbstate
      

      скріншот безмежних плазмових віджетів-kbstate в Unity

У мене було не так багато часу, щоб грати, але, wmctrlможливо, це допоможе позиціонувати, змінити розмір та зробити його на початку при запуску

Довідка: Яка команда для запуску плазмоїда kde та меню kickstart


1

Я здійснив пошук монітора клейких ключів Ubuntu і знайшов щось, що може бути корисним тут: http://code.google.com/p/key-mon/

показати скріншот

Спробуйте запустити

key-mon --sticky Підтримка липких клавіш.

Довідка: http://code.google.com/p/key-mon/

Зауважте, що версія, доступна через програмний центр, - 1.6-0ubuntu1. Вийшов у червні 2011 року, який не підтримує --sticky switch. Якщо індикатор виглядає точно так, як зазначено вище, у вас є старіша версія. Спробуйте останню версію за адресою http://code.google.com/p/key-mon/ , на момент написання це ключmon_1.17-1_all.deb 229 КБ випущено 3 січня 2014 р. Підтримка перевіреної та підтвердженої підтримки --sticky switch.


1
Приємна знахідка, проте key-monпоказує, яка кнопка була натиснута, а не стан модифікаційних клавіш . Відмінність полягає в тому, що key-monдисплей повертається до стану, що не натискається, через 1 секунду після натискання кнопки . Аплет стану модифікатора клавіатури поверне дисплей у нестиснений стан при наступному натисканні клавіші і, отже, відключить стан "натиснутого" .
dotancohen

повторно відредагована відповідь.
Старійшина Гек

Вибачте за непорозуміння. Я відредагував відповідь (знову), щоб вказати саме те, що вам потрібно.
Старійшина Гек

1
Дякую, старшина Гік. --stickyВаріант здається вгадати стан клавіш - модифікаторів, спостерігаючи державні та інші ключі, а НЕ запитуючи відповідний інтерфейс , як зробити правильний клавіатури модифікатор стану аплети. Це можна побачити, натиснувши клавішу модифікатора двічі: перший раз активує індикатор в аплеті, але другий раз не відпускає його. Таким чином, держава помилково повідомляється як активна, коли її немає. Ця пов’язана помилка вирішує проблему частково, я заповнити там деталі та додаткові помилки. Дякую.
dotancohen

1
@dotancohen Я перевірив на основі вашої заяви про те, що "аплет стану модифікатора клавіатури поверне дисплей у нестиснений стан, коли відбудеться наступне натискання клавіші, і тому відключить стан" натиснутого "." і мені ніколи не спадало на думку, що хтось спеціально натисне клавішу модифікатора двічі поспіль. Мої вибачення за недогляд.
Старійшина Гек
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.