Come aggiungere un'applet di stato del modificatore di tastiera al pannello Unity?


18

Sono un utente di KDE che sta pensando di trasferirsi su Unity. A causa della disabilità manuale, utilizzo i tasti permanenti e in KDE ho un'applet nel pannello di sistema che mostra quali tasti modificatori sono attivi. Ricordo che anche Gnome aveva questa funzione, così come Windows e OS X.

Come fa un annuncio l'applicatore del modificatore di tastiera a indicare il pannello in Unity?

Chiarimento: ho già abilitato i tasti permanenti. Sto chiedendo come aggiungere un'applet che indica lo stato dei tasti modificatori . Questo indicatore mostrerebbe quando viene premuto il tasto Maiusc, quando viene premuto il tasto Alt, quando viene premuto il tasto Tux e quando viene premuto il tasto Ctrl. Questa applet esiste in tutti i principali ambienti desktop (KDE, Windows, Mac OSX e Gnome). È necessario per l'accessibilità del desktop.

Ecco un'immagine dell'applet di stato del modificatore di tastiera, accanto all'applet dell'indicatore del layout di tastiera. I modificatori rappresentate sono, da sinistra a destra, Shift, Ctrl, Alt, I-dont-know-this-one, Tux/Win, NumLock, e CapsLock. Si può vedere che il tasto Bloc Num è attivo.

inserisci qui la descrizione dell'immagine


Errr ... Sembra che ci sia un grande vuoto quando si tratta di questo ... C'è qualcosa da emettere un suono quando si preme un tasto modificatore.
Wilf,

@wilf Se non sbaglio c'è un'icona Accessibilità in Unity (uguale a Gnome 3) ma non un'icona "extra" per informare l'utente sullo stato.
Braiam

4
@Takkat: grazie per il suggerimento. indicator-keylockvisualizza solo lo stato di tali chiavi che tradizionalmente indicatori di stato sulla tastiera stessa: CapsLock, ScrollLock, NumLock. Ho bisogno di un indicatore che mostra lo stato dei tasti modificatori normali: Shift, Ctrl, Tux, Alt. Tutti i principali desktop (KDE, Windows, Mac OSX) hanno questa applet indicatore disponibile.
dotancohen,

1
Credo che lo sia anche il nome del pacchetto dello strumento KDE a cui ti riferisci plasma-widget-kbstatee una rapida ricerca nel centro software non tiene conto di alcun risultato equivalente
Daniel W.

2
@shengy: sto usando il plasmoide KB State. Se sei su Kubuntu, installalo con sudo apt-get install plasma-widget-kbstate.
dotancohen,

Risposte:


7

Questo è un problema eccezionale in Unity:

Il codice seguente è stato aggiornato, ora può utilizzare le icone per mostrare lo stato. Ma a volte potrebbe rallentare poiché devo aggiornare il file icona sul disco rigido e ricaricarlo di nuovo. (Vedi note su questo problema / limitazione in libappindicator)

Una versione ben confezionata è stata resa disponibile su webupd8 ppa (grazie a Alin Andrei / Andrew /)

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

Riferimento: modificatori di tastiera Indicatore di stato per Ubuntu: indicatore Xkbmod


Risposta originale:

Non ci si aspetta che questa sia una risposta canonica alla domanda. Potrebbe essere contato come una soluzione. Saltare qualcuno scrive una soluzione sofisticata per questo.

Questo è un semplice indicatore prototipo di modificatori di tastiera per Unity.

Immagine a partire da sinistra: Icona, Maiusc, Maiuscole bloccate, Ctrl, Alt, Super, Alt bloccato (Cerchio piccolo per indicare lo stato bloccato)

screenshot del prototipo di unity-xkbmod

File sorgente 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. Installazione delle intestazioni / librerie necessarie: (Non sono sicuro che mi manchi)

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

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

    ./unity-xkbmod
    

Nota:

  • libappindicatorutilizzato per gli indicatori Unity manca di una funzionalità importante che facilita il porting di altri indicatori desktop. Vedi Bug # 812067 API necessaria: supporto impostazione icona pixbuf

    Senza questa funzione, diciamo che abbiamo bisogno di (Maiusc, Ctrl, Alt, AltGr, Super) con i tasti permanenti attivi; abbiamo 3 stati principali per ciascuno (Off, On / Latched, Locked). Quindi dovrebbero essere generate 3 ^ 5 icone combinate. (Dove caso normale solo 3x5 icone singole)

    Ecco perché ho usato l'etichetta indicatore con i simboli del font DejaVu Sans .

  • Per mettere un'icona, inserirla nella stessa cartella e denominarla icon.*. Formati accettati: png, svg, ico, xpm ...

    Se non ti piace alcuna icona, crea invece un'immagine 1x1 px.

Riferimenti:


Bello grazie! Ci proverò e ti ricontatterò. Ottimo lavoro, Sneetsher!
dotancohen,

Che schifo!
dotancohen,

sì, grazie @dotancohen. Quindi almeno puoi usare Unity, potrebbe essere brutto senza icone di posizione fissa?
user.dz,

1
Non mi dispiace brutto, dovresti vedere una mia foto! Ho citato questo problema sul bugtracker di Ubuntu .
dotancohen,

1
Sneetsher, volevo ringraziarti di nuovo. Ora mi sono trasferito su Unity e il passaggio sarebbe stato impossibile senza questa formidabile applicazione. Ho anche imparato parecchio dal codice. Grazie!
dotancohen,

2

Un'altra soluzione che non è perfetta, ma alcuni potrebbero trovare utile in quanto è possibile avere la piena funzionalità come in KDE come attivare una mod con un clic.

  1. installa kbstateapplet

    sudo apt-get install plasma-widget-kbstate kde-workspace-bin
    
  2. Eseguilo nel plasma-windowedgiocatore

    • Finestra normale

      plasma-windowed kbstate
      

      screenshot di plasma-widget-kbstate in Xubuntu

    • Finestra senza bordi

      plasma-windowed --noborder kbstate
      

      screenshot di plasma-widget-kbstate senza bordi in Unity

Non ho avuto molto tempo con cui giocare, ma potrei wmctrlaiutare a posizionarlo, ridimensionarlo e arrivare in cima al lancio.

Riferimento: quale comando per avviare un plasmoide kde e il menu kickstart


1

Ho fatto una ricerca per monitorare i tasti appiccicosi di Ubuntu e ho trovato qualcosa che può essere utile qui: http://code.google.com/p/key-mon/

screenshot della vetrina

Prova a correre

key-mon --sticky per supporto per chiavi adesive.

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

Si noti che la versione disponibile tramite il software center è 1.6-0ubuntu1. Rilasciato a giugno del 2011 che non supporta l'opzione --sticky. Se l'indicatore appare esattamente come sopra hai la versione precedente Prova la versione più recente su http://code.google.com/p/key-mon/ al momento della stesura di questo è keymon_1.17-1_all.deb 229 KB Rilasciato 3 gennaio 2014. Supporto per --sticky switch testato e confermato.


1
Nice find, tuttavia key-monmostra quale pulsante è stato premuto e non lo stato dei tasti modificatori . La distinzione è che il key-mondisplay ritorna allo stato non premuto 1 secondo dopo la pressione del pulsante . Un'applet di stato del modificatore di tastiera riporta lo schermo allo stato non premuto quando si verifica la successiva pressione dei tasti e quindi disabilita lo stato "premuto" .
dotancohen,

risposta modificata.
Elder Geek,

Dispiace per la confusione. Ho modificato la risposta (di nuovo) per fornire esattamente ciò di cui hai bisogno.
Elder Geek,

1
Grazie anziano Geek. L' --stickyopzione sembra indovinare lo stato dei tasti modificatori osservando lo stato di altri tasti, invece di interrogare l'interfaccia corretta come applet di stato modificatore tastiera corretto. Questo può essere visto premendo due volte un tasto modificatore: la prima volta abilita l'indicatore nell'applet, ma la seconda volta non lo rilascia. Pertanto, lo stato viene erroneamente segnalato come attivo quando non lo è. Questo bug correlato risolve parzialmente il problema, inserirò i dettagli lì e in altri bug. Grazie.
dotancohen,

1
@dotancohen Ho verificato in base alla tua affermazione che "Un'applet di stato del modificatore di tastiera restituisce il display allo stato non compresso quando si verifica la successiva pressione dei tasti e quindi disabilita lo stato" premuto ". e non mi sono mai reso conto che qualcuno avrebbe premuto il tasto modificatore due volte di seguito apposta. Mi scuso per la supervisione.
Elder Geek,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.