Jak dodać aplet stanu modyfikatora klawiatury do panelu Unity?

18

Jestem użytkownikiem KDE, który myśli o przejściu na Unity. Z powodu niepełnosprawności manualnej używam lepkich klawiszy, aw KDE mam aplet w panelu systemowym, który pokazuje, które klawisze modyfikujące są aktywne. Pamiętam, że Gnome również miał tę funkcję, podobnie jak Windows i OS X.

W jaki sposób jedna reklama apletu modyfikatora klawiatury informuje o panelu w Unity?

Wyjaśnienie: Mam już włączone lepkie klucze. Pytam, jak dodać aplet, który wskazuje stan klawiszy modyfikujących . Wskaźnik ten pokazuje, kiedy klawisz Shift jest wciśnięty, gdy klawisz Alt jest wciśnięty, kiedy klawisz Tux jest wciśnięty, a gdy klawisz Ctrl jest wciśnięty. Ten aplet istnieje we wszystkich głównych środowiskach komputerowych (KDE, Windows, Mac OSX i Gnome). Jest to konieczne dla ułatwienia dostępu do pulpitu.

Oto obraz apletu stanu modyfikatora klawiatury, obok apletu wskaźnika układu klawiatury. Modyfikatory reprezentowane są od lewej do prawej, Shift, Ctrl, Alt, I-dont-know-this-one, Tux/Win, NumLock, i CapsLock. Można zauważyć, że klawisz NumLock jest aktywny.

wprowadź opis zdjęcia tutaj

dotancohen
źródło
Errr ... Wydaje się, że istnieje duża przerwa, jeśli chodzi o to ... Jest jednak coś, co można usłyszeć po naciśnięciu klawisza modyfikatora.
Wilf
@wilf Jeśli się nie mylę, w Unity znajduje się ikona dostępności (taka sama jak w Gnome 3), ale nie ikona „dodatkowa”, która informuje użytkownika o statusie.
Braiam
4
@Takkat: Dziękuję za sugestię. indicator-keylocktylko wyświetla stan tych kluczy, które tradycyjnie mają wskaźniki stanu na klawiaturze samej: CapsLock, ScrollLock, NumLock. Muszę pomocą wskaźnika, obrazującego stan standardowych kluczy modyfikatorów: Shift, Ctrl, Tux, Alt. Wszystkie główne komputery stacjonarne (KDE, Windows, Mac OSX) mają ten aplet wskaźnika.
dotancohen
1
Sądzę, że nazwa pakietu narzędzia KDE, do którego się odwołujesz, jest taka, plasma-widget-kbstatea szybkie wyszukiwanie w centrum oprogramowania rzeczywiście nie uwzględnia równoważnych wyników
Daniel W.,
2
@shengy: Używam plazmoidu KB State. Jeśli korzystasz z Kubuntu, zainstaluj go przy pomocy sudo apt-get install plasma-widget-kbstate.
dotancohen

Odpowiedzi:

7

Jest to nierozstrzygnięty problem w Unity:

Poniższy kod został zaktualizowany, teraz może używać ikon do wyświetlania stanu. Ale może czasem zwolnić, ponieważ muszę zaktualizować plik ikony na dysku twardym, a następnie ponownie go załadować. (Zobacz uwagi na temat tego problemu / ograniczenia w libappindicator)

Dobrze zapakowane wydanie zostało udostępnione na webupd8 ppa (Podziękowania dla Alin Andrei / Andrew /)

sudo add-apt-repository ppa:nilarimogard/webupd8
sudo apt-get update
sudo apt-get install indicator-xkbmod

Odniesienie: Klawiatura Modyfikatory Wskaźnik stanu Ubuntu: Xkbmod Indicator


Oryginalna odpowiedź:

Nie jest to kanoniczna odpowiedź na pytanie. Można to uznać za obejście. Hopping ktoś pisze dla niego wyrafinowane rozwiązanie.

To prosty prototypowy modyfikator klawiatury dla Unity.

Obraz zaczyna się od lewej: Ikona, Shift, Zablokowane klawisze, Ctrl, Alt, Super, Zablokowany AltGr (Małe kółko wskazujące stan zablokowany)

zrzut ekranu prototypu unity-xkbmod

Plik źródłowy 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. Instalowanie potrzebnych nagłówków / bibliotek: (Nie jestem pewien, czy coś przegapię)

    sudo apt-get install libx11-dev libappindicator-dev libgtk2.0-dev
    
  2. Kompilacja:

    gcc -Wall unity-xkbmod.c -o unity-xkbmod `pkg-config --cflags --libs appindicator-0.1` -lX11
    
  3. Biegać:

    ./unity-xkbmod
    

Uwaga:

  • libappindicatorużywane dla wskaźników Unity nie mają ważnej funkcji, która ułatwia przenoszenie innych wskaźników na komputery stacjonarne. Zobacz Bug # 812067 Potrzebny interfejs API: obsługa ustawień ikon pixbuf

    Bez tej funkcji, powiedzmy, że potrzebujemy (Shift, Ctrl, Alt, AltGr, Super) z aktywnymi lepkimi klawiszami; mamy 3 główne statusy dla każdego (Wyłączone, Włączone / Zatrzaśnięte, Zablokowane). Tak więc należy wygenerować 3 ^ 5 połączonych ikon. (W normalnych przypadkach tylko 3 x 5 pojedynczych ikon)

    Dlatego użyłem etykiety wskaźnika z symbolami z czcionki DejaVu Sans .

  • Aby umieścić ikonę, umieść ją w tym samym folderze i nadaj jej nazwę icon.*. Akceptowane formaty: png, svg, ico, xpm ...

    Jeśli nie podoba Ci się żadna ikona, po prostu utwórz obraz 1x1 px.

Bibliografia:

user.dz
źródło
Fajnie, dziękuję! Spróbuję i wrócę do ciebie. Świetna robota, Sneetsher!
dotancohen
Że sneetsher!
dotancohen
tak, dziękuję @dotancohen. Więc przynajmniej możesz użyć Unity, może to brzydkie bez ikon ustalonej pozycji?
user.dz
1
Nie mam nic przeciwko brzydkości, powinieneś zobaczyć moje zdjęcie! Wspomniałem o tym problemie na bugtrackerze Ubuntu .
dotancohen
1
Sneetsher, chciałem jeszcze raz podziękować. Teraz przeniosłem się do Unity i ruch ten byłby niemożliwy bez tej wspaniałej aplikacji. Nauczyłem się również sporo z kodu. Dziękuję Ci!
dotancohen
2

Kolejne rozwiązanie, które nie jest idealne, ale niektórym może się przydać, ponieważ można mieć pełną funkcjonalność, tak jak w KDE, np. Aktywować mod za pomocą kliknięcia.

  1. zainstaluj kbstateaplet

    sudo apt-get install plasma-widget-kbstate kde-workspace-bin
    
  2. Uruchom to plasma-windowed odtwarzaczu

    • Zwykłe okno

      plasma-windowed kbstate
      

      zrzut ekranu plazmy-widget-kbstate w Xubuntu

    • Okno bez obramowania

      plasma-windowed --noborder kbstate
      

      zrzut ekranu bezgranicznego widgetu-plazmy-kbstate w Unity

Nie miałem dużo czasu na zabawę, ale wmctrlmoże pomóc w ustawieniu, zmianie rozmiaru i zdobyciu przewagi na starcie.

Odniesienie: Jakie polecenie, aby uruchomić plazmid KDE i menu kickstart

user.dz
źródło
1

Poszukałem monitora lepkich klawiszy Ubuntu i znalazłem coś, co może być pomocne tutaj: http://code.google.com/p/key-mon/

pokaż zrzut ekranu

Spróbuj uruchomić

key-mon --sticky do obsługi lepkich kluczy.

Odniesienie: http://code.google.com/p/key-mon/

Pamiętaj, że wersja dostępna za pośrednictwem centrum oprogramowania to 1.6-0ubuntu1. Wydany w czerwcu 2011 roku, który nie obsługuje przełącznika --sticky. Jeśli wskaźnik wygląda dokładnie tak, jak powyżej, masz starszą wersję Wypróbuj najnowszą wersję na http://code.google.com/p/key-mon/ od tego momentu jest to keymon_1.17-1-1all.deb 229 KB Wydany 3 stycznia 2014. Obsługa testowania przełącznika kleistego przetestowana i potwierdzona.

Starszy Geek
źródło
1
Niezłe znalezisko key-monpokazuje jednak , który przycisk został naciśnięty, a nie stan klawiszy modyfikujących . Różnica polega na tym, że key-monwyświetlacz powraca do stanu nie naciśniętego 1 sekundę po naciśnięciu przycisku . Aplet stanu modyfikatora klawiatury przywróci wyświetlacz do stanu nie naciśniętego, gdy nastąpi kolejne naciśnięcie klawisza, i tym samym wyłączy stan „wciśnięty” .
dotancohen
ponownie zredagowana odpowiedź.
Starszy Geek
Przepraszam za zamieszanie. Zredagowałem odpowiedź (ponownie), aby zapewnić dokładnie to, czego potrzebujesz.
Starszy Geek
1
Dziękuję Starszemu Geekowi. --stickyOpcja wydaje się odgadnąć stan modyfikatora kluczy oglądając Państwowej inne klucze, zamiast odpytywania właściwego interfejsu jak zrobić właściwy klawiaturowych apletów państwowych modyfikator. Można to zobaczyć, naciskając dwukrotnie klawisz modyfikujący: pierwszy raz włącza wskaźnik w aplecie, ale drugi raz go nie zwalnia. Tak więc stan jest błędnie zgłaszany jako aktywny, gdy nie jest aktywny. Ten pokrewny błąd częściowo rozwiązuje problem, podam tam szczegóły i dodatkowe błędy. Dziękuję Ci.
dotancohen
1
@dotancohen Przetestowałem na podstawie twojego stwierdzenia, że ​​„Aplet stanu modyfikatora klawiatury przywróciłby wyświetlacz do stanu nie wciśniętego, gdy nastąpiłoby kolejne naciśnięcie klawisza, a zatem dezaktywowałby stan„ wciśnięty ”. i nigdy nie przyszło mi do głowy, że ktoś celowo wcisnął klawisz modyfikujący dwa razy z rzędu. Przepraszam za niedopatrzenie.
Starszy Geek