¿Cómo agregar un applet de estado de modificador de teclado al panel de Unity?

18

Soy un usuario de KDE que está pensando en mudarse a Unity. Debido a una discapacidad manual, uso teclas adhesivas y en KDE tengo un applet en el panel del sistema que muestra qué teclas de modificación son activo. Recuerdo que Gnome también tenía esta característica, al igual que Windows y OS X.

¿Cómo se agrega el applet de estado del modificador de teclado al panel en Unity?

Aclaración: ya habilité las teclas adhesivas. Estoy preguntando cómo agregar un applet que indica el estado de las teclas modificadoras . Este indicador se mostraría cuando se presione la tecla Shift, cuando se presione la tecla Alt, cuando se presione la tecla Tux y cuando se presione la tecla Ctrl. Este applet existe en todos los entornos de escritorio principales (KDE, Windows, Mac OSX y Gnome). Es necesario para la accesibilidad del escritorio.

Aquí hay una imagen del applet de estado del modificador del teclado, junto al applet del indicador de diseño del teclado. Los modificadores representados son, de izquierda a derecha, Shift , Ctrl , Alt , I-dont-know-this-one , Tux/Win , NumLock y CapsLock . Se puede ver que la tecla Bloq Num está activa.

    
pregunta dotancohen 08.01.2014 - 16:46

3 respuestas

6

Este es un problema pendiente en Unity:

El código siguiente se ha actualizado, ahora puede usar iconos para mostrar el estado. Pero puede ser lento en algún momento, ya que tengo que actualizar el archivo de icono en el disco duro y luego volver a cargarlo. (Consulte las notas sobre este problema / limitación en libappindicator )

Una versión bien empaquetada se puso a disposición en webupd8 ppa (Gracias a Alin Andrei / Andrew /)

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

Referencia: Modificadores de teclado Indicador de estado para Ubuntu: Indicador Xkbmod

Respuesta original:

No se trata de una respuesta canónica a la pregunta. Se podría contar como una solución alternativa. Saltando, alguien escribe soluciones sofisticadas para ello.

Este es un indicador de modificadores de teclado prototipo simple para Unity.

Imagen que comienza desde la izquierda: Icono, Mayús, Bloq Mayús, Ctrl, Alt, Super, Bloq Alt. (Círculo pequeño para indicar estado bloqueado)

Archivo de origen 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. Instalar encabezados / librerías necesarios: (No estoy seguro de si omito alguno)

    sudo apt-get install libx11-dev libappindicator-dev libgtk2.0-dev
    
  2. Compilación:

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

    ./unity-xkbmod
    

Nota:

  • libappindicator utilizado para los indicadores de Unity carecen de una característica importante que facilite a los puertos otros indicadores de los escritorios. Consulte el error # 812067 API necesaria: compatibilidad con la configuración del icono de pixbuf

    Sin esta función, digamos que necesitamos (Shift, Ctrl, Alt, AltGr, Super) con las teclas adhesivas activas; tenemos 3 estados principales para cada uno (Apagado, Encendido / Enclavado, Bloqueado). Por lo tanto, se deben generar 3 ^ 5 iconos combinados. (En el caso normal, solo 3x5 iconos individuales)

    Es por eso que utilicé una etiqueta indicadora con símbolos de la fuente DejaVu Sans .

  • Para poner un icono, colóquelo en la misma carpeta y asígnele el nombre icon.* . Formatos aceptados: png, svg, ico, xpm ...

    Si no te gusta ningún ícono, solo crea una imagen de 1x1 px en su lugar.

Referencias:

respondido por el user.dz 30.03.2014 - 22:48
2

Otra solución que no es perfecta, pero a algunos les puede resultar útil, ya que es posible tener una funcionalidad completa como en KDE, como activar un mod con un clic.

  1. install kbstate applet

    sudo apt-get install plasma-widget-kbstate kde-workspace-bin
    
  2. Ejecútalo en plasma-windowed player

    • Ventana regular

      plasma-windowed kbstate
      

    • Ventana sin bordes

      plasma-windowed --noborder kbstate
      

No tenía mucho tiempo para jugar, pero wmctrl puede ayudar a posicionar, cambiar el tamaño y hacerlo en la parte superior al inicio.

Referencia: Qué comando lanzar un kde plasmoid y el menú kickstart

    
respondido por el user.dz 15.02.2015 - 00:18
1

Hice una búsqueda del monitor de claves adhesivas de Ubuntu y encontré algo que podría ser útil aquí: enlace

Prueba a ejecutar

key-mon --sticky para Soporte para teclas adhesivas.

Referencia: enlace

Tenga en cuenta que la versión disponible a través del centro de software es 1.6-0ubuntu1. Lanzado en junio de 2011, que no es compatible con el switch --sticky. Si el indicador se ve exactamente como el de arriba, tiene la versión anterior Pruebe la última versión en enlace . al momento de escribir este artículo, es keymon_1.17-1_all.deb 229 KB publicado el 3 de enero de 2014. Soporte para el switch --sticky probado y confirmado.

    
respondido por el Elder Geek 11.03.2014 - 15:05

Lea otras preguntas en las etiquetas