Bagaimana cara menambahkan applet state modifier keyboard ke panel Unity?


18

Saya adalah pengguna KDE yang berpikir untuk pindah ke Unity. Karena cacat manual, saya menggunakan kunci lengket dan di KDE saya memiliki applet di panel sistem yang menunjukkan kunci pengubah mana yang aktif. Saya ingat bahwa Gnome memiliki fitur ini juga, begitu juga Windows dan OS X.

Bagaimana cara seseorang memasang applet state modifier keyboard ke panel di Unity?

Klarifikasi: Saya sudah mengaktifkan kunci tempel. Saya bertanya bagaimana cara menambahkan applet yang menunjukkan keadaan tombol pengubah . Indikator ini akan ditampilkan ketika tombol Shift ditekan, ketika tombol Alt tertekan, ketika tombol Tux tertekan, dan ketika tombol Ctrl ditekan. Applet ini ada di semua lingkungan desktop utama (KDE, Windows, Mac OSX, dan Gnome). Ini diperlukan untuk aksesibilitas desktop.

Berikut adalah gambar applet pengubah keyboard, di sebelah applet indikator tata letak keyboard. Pengubah diwakili adalah, dari kiri ke kanan, Shift, Ctrl, Alt, I-dont-know-this-one, Tux/Win, NumLock, dan CapsLock. Dapat dilihat bahwa kunci NumLock aktif.

masukkan deskripsi gambar di sini


Errr ... Tampaknya ada celah besar dalam hal ini ... Ada hal yang harus terdengar ketika tombol pengubah ditekan.
Wilf

@wilf Jika saya tidak salah, ada ikon Aksesibilitas di Unity (sama dengan Gnome 3) tetapi bukan ikon "ekstra" untuk memberi tahu pengguna tentang status.
Braiam

4
@ Takkat: Terima kasih atas sarannya. indicator-keylockhanya menampilkan keadaan orang-orang kunci yang secara tradisional memiliki indikator negara pada keyboard itu sendiri: CapsLock, ScrollLock, NumLock. Saya perlu indikator yang menunjukkan keadaan tombol pengubah standar: Shift, Ctrl, Tux, Alt. Semua desktop utama (KDE, Windows, Mac OSX) menyediakan applet indikator ini.
dotancohen

1
Saya percaya nama paket alat KDE yang Anda rujuk juga plasma-widget-kbstatedan pencarian cepat di pusat perangkat lunak memang tidak mengindahkan hasil yang setara
Daniel W.

2
@ Loty: Saya menggunakan plasmoid KB State. Jika Anda menggunakan Kubuntu, instal dengan sudo apt-get install plasma-widget-kbstate.
dotancohen

Jawaban:


7

Ini adalah masalah besar di Unity:

Kode di bawah ini telah diperbarui, sekarang dapat menggunakan ikon untuk menunjukkan status. Tetapi kadang-kadang mungkin lambat karena saya harus memperbarui file ikon pada hard drive kemudian memuatnya lagi. (Lihat catatan tentang masalah / batasan ini di libappindicator)

Rilis yang dikemas dengan baik tersedia di webupd8 ppa (Terima kasih kepada Alin Andrei / Andrew /)

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

Referensi: Pengubah Keyboard Indikator keadaan Untuk Ubuntu: Indikator Xkbmod


Jawaban asli:

Ini tidak dihadiri untuk menjadi jawaban kanonik untuk pertanyaan itu. Itu bisa dihitung sebagai pekerjaan di sekitar. Melompat seseorang menulis solusi canggih untuk itu.

Ini adalah indikator pengubah keyboard prototipe sederhana untuk Unity.

Gambar mulai dari kiri: Ikon, Shift, Caps Terkunci, Ctrl, Alt, Super, AltGr Terkunci (Lingkaran kecil untuk menunjukkan keadaan terkunci)

tangkapan layar prototipe unity-xkbmod

File sumber 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. Menginstal header / lib yang diperlukan: (Tidak yakin jika saya melewatkan)

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

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

    ./unity-xkbmod
    

catatan:

  • libappindicatordigunakan untuk indikator Unity tidak memiliki fitur penting yang memudahkan untuk port indikator desktop lainnya. Lihat Bug # 812067 API diperlukan: dukungan pengaturan ikon pixbuf

    Tanpa fitur ini, katakanlah kita perlu (Shift, Ctrl, Alt, AltGr, Super) dengan kunci lengket aktif; kami memiliki 3 status utama untuk masing-masing (Off, On / Latched, Locked). Jadi 3 ^ 5 ikon gabungan harus dihasilkan. (Dimana case biasa hanya 3x5 ikon tunggal)

    Itu sebabnya saya menggunakan label indikator dengan simbol dari font DejaVu Sans .

  • Untuk meletakkan ikon, letakkan di folder yang sama dan beri nama icon.*. Format yang diterima: png, svg, ico, xpm ...

    Jika Anda tidak menyukai ikon apa pun, buat saja gambar 1x1 px.

Referensi:


Baik, terima kasih! Saya akan mencoba ini dan kembali kepada Anda. Kerja bagus, Sneetsher!
dotancohen

Bahwa kau berselingkuh!
dotancohen

ya, terima kasih @dotancohen. Jadi setidaknya Anda bisa menggunakan Unity, mungkin itu jelek tanpa ikon posisi tetap?
user.dz

1
Saya tidak keberatan jelek, Anda harus melihat foto saya! Saya telah menyebutkan masalah ini di bugtracker Ubuntu .
dotancohen

1
Sneetsher, aku ingin mengucapkan terima kasih lagi. Saya sekarang telah pindah ke Unity dan langkah itu tidak akan mungkin tanpa aplikasi hebat ini. Saya juga belajar sedikit dari kode. Terima kasih!
dotancohen

2

Solusi lain yang tidak sempurna, tetapi beberapa mungkin merasa berguna karena dimungkinkan untuk memiliki fungsionalitas penuh seperti di KDE seperti mengaktifkan mod dengan klik.

  1. instal kbstateapplet

    sudo apt-get install plasma-widget-kbstate kde-workspace-bin
    
  2. Jalankan di plasma-windowedplayer

    • Jendela biasa

      plasma-windowed kbstate
      

      tangkapan layar plasma-widget-kbstate di Xubuntu

    • Jendela tanpa batas

      plasma-windowed --noborder kbstate
      

      tangkapan layar plasma-widget-kbstate tanpa batas di Unity

Saya tidak punya banyak waktu untuk bermain, tetapi wmctrldapat membantu memposisikan, mengubah ukuran, dan menjadikannya teratas saat diluncurkan.

Referensi: Perintah apa untuk meluncurkan plasmoid KDE dan menu kickstart


1

Saya melakukan pencarian untuk memantau kunci lengket Ubuntu dan menemukan sesuatu yang mungkin membantu di sini: http://code.google.com/p/key-mon/

tampilkan tangkapan layar case

Coba jalankan

key-mon --sticky untuk Dukungan untuk kunci lengket.

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

Perhatikan bahwa versi yang tersedia melalui pusat perangkat lunak adalah 1.6-0ubuntu1. Dirilis Juni 2011 yang tidak mendukung saklar --sticky. Jika indikatornya persis seperti di atas, Anda memiliki versi yang lebih lama. Coba versi terbaru di http://code.google.com/p/key-mon/ saat tulisan ini dibuat, keymon_1.17-1_all.deb 229 KB Dirilis 3 Januari 2014. Dukungan untuk sakelar --sticky diuji dan dikonfirmasi.


1
Nice find, namun key-monmenunjukkan tombol mana yang ditekan dan bukan keadaan tombol pengubah . Perbedaannya adalah bahwa key-montampilan kembali ke keadaan tidak ditekan 1 detik setelah tombol ditekan . Applet pengubah keyboard akan mengembalikan tampilan ke keadaan tidak ditekan saat penekanan tombol berikutnya terjadi dan karenanya menonaktifkan kondisi 'ditekan' .
dotancohen

diedit kembali jawaban.
Penatua Geek

Maaf bila membingungkan. Saya telah mengedit jawaban (lagi) untuk memberikan apa yang Anda butuhkan.
Penatua Geek

1
Terima kasih Penatua Geek. The --stickypilihan tampaknya menebak keadaan tombol pengubah dengan menonton kunci lain negara, bukan query interface yang tepat seperti yang dilakukan keyboard yang tepat applet negara pengubah. Ini dapat dilihat dengan menekan tombol pengubah dua kali: pertama kali mengaktifkan indikator dalam applet, tetapi kedua kalinya tidak melepaskannya. Dengan demikian, negara dilaporkan secara salah sebagai aktif padahal tidak. Bug terkait ini mengatasi masalah ini sebagian, saya akan mengisi rincian di sana dan bug tambahan. Terima kasih.
dotancohen

1
@dotancohen Saya menguji berdasarkan pada pernyataan Anda bahwa "Applet state modifier keyboard akan mengembalikan tampilan ke keadaan tidak tertekan ketika penekanan tombol berikutnya akan terjadi dan karenanya menonaktifkan keadaan 'ditekan'." dan saya tidak pernah sadar bahwa ada orang yang akan menekan tombol pengubah dua kali berturut-turut dengan sengaja. Saya minta maaf atas pengawasannya.
Penatua Geek
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.