web-dev-qa-db-fra.com

Comment ajouter une applet d'état de modificateur de clavier au panneau Unity?

Je suis un utilisateur de KDE qui envisage de passer à Unity. En raison d’un handicap manuel, j’utilise touches adhésives et dans KDE, j’ai un applet dans le panneau système qui indique les touches de modification actives. Je me souviens que Gnome avait aussi cette fonctionnalité, de même que Windows et OS X.

Comment peut-on ajouter l'applet d'état du modificateur de clavier au panneau dans Unity?

Clarification: J'ai déjà activé les touches rémanentes. Je demande comment ajouter une applet qui indique l'état des touches de modification . Cet indicateur indiquerait quand la touche Shift est enfoncée, quand la touche Alt est enfoncée, quand la touche Tux est enfoncée et quand la touche Ctrl est enfoncée. Cette applet existe dans tous les principaux environnements de bureau (KDE, Windows, Mac OSX et Gnome). C'est nécessaire pour l'accessibilité du bureau.

Voici une image de l'applet d'état de modificateur de clavier, à côté de l'applet d'indicateur de disposition du clavier. Les modificateurs représentés sont, de gauche à droite, Shift, Ctrl, Alt, I-dont-know-this-one, Tux/Win, NumLock et CapsLock. On peut voir que la touche NumLock est active.

enter image description here

18
dotancohen

C'est une question en suspens dans Unity:

Le code ci-dessous a été mis à jour, il peut maintenant utiliser des icônes pour afficher l'état. Mais cela peut être lent parfois car je dois mettre à jour le fichier icône sur le disque dur, puis le recharger à nouveau. (Voir les notes sur ce problème/cette limitation dans libappindicator)

Une version bien emballée a été mise à disposition sur webupd8 ppa (Merci à Alin Andrei/Andrew /)

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

Référence: Indicateur d'état des modificateurs de clavier pour Ubuntu: indicateur Xkbmod


Réponse originale:

Ceci n'est pas considéré comme une réponse canonique à la question. Cela pourrait être considéré comme un moyen de contourner le problème. Hopping quelqu'un écrit une solution sophistiquée pour cela.

Ceci est un indicateur simple de modificateurs de clavier prototype pour Unity.

Image commençant par la gauche: Icône, Maj, Majuscule verrouillée, Ctrl, Alt, Super, AltGr verrouillée (Un petit cercle pour indiquer l'état verrouillé)

screenshot of unity-xkbmod prototype

Fichier source 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. Installer les en-têtes/libs nécessaires: (Pas sûr si j'en manque)

    Sudo apt-get install libx11-dev libappindicator-dev libgtk2.0-dev
    
  2. Compilation:

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

    ./unity-xkbmod
    

Remarque:

  • libappindicator utilisé pour les indicateurs Unity manque d'une fonctionnalité importante qui facilite le portage d'autres indicateurs de bureau. Voir le bogue 812067 API nécessaire: prise en charge de la configuration des icônes pixbuf

    Sans cette fonctionnalité, supposons que nous ayons besoin de (Maj, Ctrl, Alt, AltGr, Super) avec les touches collantes actives; nous avons 3 états principaux pour chacun (Désactivé, Activé/Verrouillé, Verrouillé). Donc, 3 ^ 5 icônes combinées doivent être générées. (Où cas normal seulement 3x5 icônes simples)

    C'est pourquoi j'ai utilisé une étiquette d'indicateur avec les symboles de la police DejaVu Sans .

  • Pour mettre une icône, placez-la dans le même dossier et nommez-la icon.*. Formats acceptés: png, svg, ico, xpm ...

    Si vous n'aimez aucune icône, créez simplement une image 1x1 px.

Références:

7
user.dz

Une autre solution qui n’est pas parfaite, mais certains peuvent trouver cela utile car il est possible d’avoir toutes les fonctionnalités comme dans KDE, comme activer un mod en un clic.

  1. installer kbstate applet

    Sudo apt-get install plasma-widget-kbstate kde-workspace-bin
    
  2. Exécutez-le dans le lecteur plasma-windowed

    • Fenêtre régulière

      plasma-windowed kbstate
      

      screenshot of plasma-widget-kbstate in Xubuntu

    • Fenêtre sans bordure

      plasma-windowed --noborder kbstate
      

      screenshot of borderless plasma-widget-kbstate in Unity

Je n'avais pas beaucoup de temps pour jouer, mais wmctrl peut aider à positionner, redimensionner et se positionner au mieux lors du lancement.

Référence: Quelle commande pour lancer un plasmoïde kde et le menu kickstart

2
user.dz

J'ai fait une recherche sur le moniteur de touches rémanentes Ubuntu et trouvé quelque chose qui pourrait être utile ici: http://code.google.com/p/key-mon/

show case screenshot

Essayez de courir

key-mon --sticky pour la prise en charge des touches rémanentes.

Référence: http://code.google.com/p/key-mon/

Notez que la version disponible via le centre logiciel est 1.6-0ubuntu1. Paru en juin 2011 qui ne supporte pas le commutateur --sticky. Si l'indicateur ressemble exactement à ce qui précède, vous avez l'ancienne version . Essayez la dernière version à l'adresse http://code.google.com/p/key-mon/ à la date de rédaction de ce document, keymon_1.17-1_all.deb 229 Ko, publié le 3 janvier 2014. Prise en charge du commutateur --sticky testé et confirmé.

1
Elder Geek