วิธีเพิ่มแอปเพล็ตตัวปรับเปลี่ยนสถานะแป้นพิมพ์ในแผง Unity


18

ฉันเป็นผู้ใช้ KDE ที่คิดจะย้ายไปที่ Unity เนื่องจากความพิการด้วยตนเองฉันจึงใช้ปุ่มปักหมุดและใน KDE ฉันมีแอปเพล็ตในแผงระบบซึ่งแสดงว่าปุ่มตัวดัดแปลงใดทำงานอยู่ ฉันจำได้ว่า Gnome มีคุณสมบัตินี้เช่นเดียวกันดังนั้น Windows และ OS X

โฆษณาหนึ่งที่ตัวดัดแปลงคีย์บอร์ดระบุแอปเพล็ตลงในแผงใน Unity ได้อย่างไร

ชี้แจง:ฉันได้เปิดใช้งานปุ่มปักหมุดแล้ว ผมขอให้วิธีการเพิ่มแอปเพล็ซึ่งแสดงสถานะของปุ่มเครื่องปรับ ตัวบ่งชี้นี้จะปรากฏขึ้นเมื่อปุ่ม Shift ถูกกดลงเมื่อปุ่ม Alt ถูกกดเมื่อปุ่ม Tux ถูกกดลงและเมื่อปุ่ม Ctrl ถูกกด แอพเพล็ตนี้มีอยู่ในทุกสภาพแวดล้อมบนเดสก์ท็อปหลัก (KDE, Windows, Mac OSX และ Gnome) จำเป็นสำหรับการเข้าถึงเดสก์ท็อป

นี่คือภาพของแอปเพล็ตตัวดัดแปลงสถานะแป้นพิมพ์ถัดจากแอปเพล็ตตัวบ่งชี้เค้าโครงของแป้นพิมพ์ การปรับเปลี่ยนเป็นตัวแทนเป็นจากซ้ายไปขวาShift, Ctrl, Alt, I-dont-know-this-one, Tux/Win, และNumLock CapsLockจะเห็นได้ว่าปุ่ม NumLock เปิดใช้งานอยู่

ป้อนคำอธิบายรูปภาพที่นี่


เอ่อ ... ดูเหมือนว่าจะมีช่องว่างขนาดใหญ่เมื่อพูดถึงเรื่องนี้ ... มีบางอย่างที่จะส่งเสียงบี๊บเมื่อกดปุ่มตัวดัดแปลง
วิลฟ์

@wilf หากฉันไม่เข้าใจผิดว่ามีไอคอนการเข้าถึงใน Unity (เหมือนกับ Gnome 3) แต่ไม่ใช่ไอคอน "พิเศษ" เพื่อแจ้งผู้ใช้เกี่ยวกับสถานะ
Braiam

4
@ Takkat: ขอบคุณสำหรับคำแนะนำ แสดงเฉพาะสถานะของคีย์เหล่านั้นซึ่งเป็นประเพณีที่มีตัวชี้วัดของรัฐบนแป้นพิมพ์ของตัวเอง:indicator-keylock , , ฉันจำเป็นต้องใช้ตัวบ่งชี้ซึ่งแสดงให้เห็นสถานะของปุ่มปรับปรุงมาตรฐานนี้: , , , เดสก์ท็อปหลักทั้งหมด (KDE, Windows, Mac OSX) มีแอปเพล็ตตัวบ่งชี้นี้ CapsLockScrollLockNumLockShiftCtrlTuxAlt
dotancohen

1
ฉันเชื่อว่าชื่อแพ็กเก็ตของเครื่องมือ KDE ที่คุณอ้างถึงด้วยเช่นกันplasma-widget-kbstateและการค้นหาอย่างรวดเร็วในศูนย์ซอฟต์แวร์นั้นไม่ได้คำนึงถึงผลลัพธ์ที่เทียบเท่าเสมอไป
Daniel W.

2
@shengy: ฉันใช้พลาสลอยด์รัฐ KB ถ้าคุณอยู่ใน Kubuntu sudo apt-get install plasma-widget-kbstateแล้วติดตั้งด้วย
dotancohen

คำตอบ:


7

นี่เป็นปัญหาที่โดดเด่นใน Unity:

รหัสด้านล่างนี้ได้รับการอัพเดตแล้วตอนนี้สามารถใช้ไอคอนเพื่อแสดงสถานะได้ แต่มันอาจช้าลงบางครั้งเนื่องจากฉันต้องอัปเดตไฟล์ไอคอนบนฮาร์ดไดรฟ์จากนั้นโหลดซ้ำอีกครั้ง (ดูหมายเหตุเกี่ยวกับปัญหา / ข้อ จำกัด นี้libappindicator)

มีการเผยแพร่แพคเกจอย่างดีบน webupd8 ppa (ขอบคุณไปยัง Alin Andrei / Andrew /)

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

การอ้างอิง: ตัวบ่งชี้คีย์บอร์ดโมดิฟายเออร์สำหรับ Ubuntu: ตัวบ่งชี้ Xkbmod


คำตอบเดิม:

สิ่งนี้ไม่ได้เข้าร่วมเพื่อเป็นคำตอบที่ยอมรับได้สำหรับคำถาม มันอาจถูกนับว่าเป็นการหลีกเลี่ยง การกระโดดคนเขียนโซลูชันที่ซับซ้อนสำหรับมัน

ตัวบ่งชี้การดัดแปลงคีย์บอร์ดต้นแบบอย่างง่ายสำหรับ Unity

ภาพเริ่มจากซ้าย: ไอคอน, Shift, Caps Locked, Ctrl, Alt, Super, AltGr ที่ถูกล็อค (วงกลมขนาดเล็กเพื่อระบุสถานะล็อค)

สกรีนช็อตของต้นแบบ unity-xkbmod

ไฟล์ต้นฉบับ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. การติดตั้งส่วนหัว / libs ที่ต้องการ: (ไม่แน่ใจว่าฉันพลาดหรือไม่)

    sudo apt-get install libx11-dev libappindicator-dev libgtk2.0-dev
    
  2. รวบรวม:

    gcc -Wall unity-xkbmod.c -o unity-xkbmod `pkg-config --cflags --libs appindicator-0.1` -lX11
    
  3. วิ่ง:

    ./unity-xkbmod
    

บันทึก:

  • libappindicatorใช้สำหรับตัวบ่งชี้ Unity ที่ขาดคุณสมบัติที่สำคัญซึ่งทำให้ง่ายต่อการพอร์ตตัวบ่งชี้เดสก์ท็อปอื่น ๆ ดู Bug # 812067 API ที่ต้องการ: สนับสนุนการตั้งค่าไอคอน pixbuf

    หากไม่มีคุณสมบัตินี้สมมติว่าเราต้องการ (Shift, Ctrl, Alt, AltGr, Super) โดยใช้ปุ่มปักหมุดที่ใช้งานอยู่ เรามี 3 สถานะหลักสำหรับแต่ละคน (ปิด, เปิด / ล็อค, ล็อค) ดังนั้นควรสร้างไอคอนที่รวมกัน3 ^ 5 (ในกรณีปกติเพียง3x5ไอคอนเดียว)

    นั่นเป็นเหตุผลที่ฉันใช้ป้ายตัวบ่งชี้พร้อมสัญลักษณ์จากแบบอักษรDejaVu Sans

  • icon.*ที่จะนำไอคอนวางไว้ในโฟลเดอร์เดียวกันและชื่อ รูปแบบที่ยอมรับ: png, svg, ico, xpm ...

    หากคุณไม่ชอบไอคอนใด ๆ เพียงสร้างภาพ 1x1 พิกเซลแทน

อ้างอิง:


ดีมากขอบคุณ! ฉันจะลองทำสิ่งนี้และกลับไปหาคุณ เยี่ยมมาก Sneetsher!
dotancohen

ว่าคุณแอบ!
dotancohen

อ๋อขอบคุณ @dotancohen อย่างน้อยคุณก็สามารถใช้ Unity ได้นั่นอาจเป็นเรื่องน่าเกลียดหากไม่มีไอคอนตำแหน่งคงที่ใช่ไหม
user.dz

1
ฉันไม่รังเกียจน่าเกลียดคุณควรเห็นรูปของฉัน! ฉันได้กล่าวปัญหานี้ในbugtracker Ubuntu
dotancohen

1
ฉันต้องการพูดขอบคุณอีกครั้ง ตอนนี้ฉันย้ายไปที่ Unity และการย้ายนั้นเป็นไปไม่ได้หากไม่มีแอปพลิเคชันที่ยอดเยี่ยม ฉันได้เรียนรู้จากโค้ดด้วยเช่นกัน ขอขอบคุณ!
dotancohen

2

โซลูชันอื่นที่ไม่สมบูรณ์ แต่บางคนอาจพบว่ามีประโยชน์เพราะเป็นไปได้ที่จะมีฟังก์ชั่นเต็มรูปแบบเหมือนกับใน KDE เช่นเปิดใช้งาน mod ด้วยการคลิก

  1. ติดตั้งkbstateแอพเพล็ต

    sudo apt-get install plasma-widget-kbstate kde-workspace-bin
    
  2. เรียกใช้ในโปรแกรมplasma-windowedเล่น

    • หน้าต่างปกติ

      plasma-windowed kbstate
      

      สกรีนช็อตของ plasma-widget-kbstate ใน Xubuntu

    • หน้าต่างไร้ขอบ

      plasma-windowed --noborder kbstate
      

      สกรีนช็อตของ plasma-widget-kbstate แบบไร้ขอบใน Unity

ฉันไม่มีเวลามากที่จะเล่นด้วย แต่wmctrlอาจช่วยให้ตำแหน่งปรับขนาดและทำให้มันอยู่ด้านบนที่เปิดตัว

การอ้างอิง: คำสั่งใดที่จะเรียกใช้ kde plasmoid และเมนู kickstart


1

ฉันได้ทำการค้นหา Ubuntu Sticky Monitor และพบสิ่งที่อาจเป็นประโยชน์ที่นี่: http://code.google.com/p/key-mon/

แสดงภาพหน้าจอเคส

ลองวิ่ง

key-mon --sticky สำหรับการสนับสนุนสำหรับปุ่มปักหมุด

การอ้างอิง: http://code.google.com/p/key-mon/

โปรดทราบว่ารุ่นที่มีให้บริการผ่านศูนย์ซอฟต์แวร์คือ 1.6-0ubuntu1 เผยแพร่เมื่อเดือนมิถุนายน 2554 ซึ่งไม่รองรับสวิตช์ --sticky ถ้าตัวบ่งชี้ลักษณะเหมือนกับข้างต้นคุณมีรุ่นเก่าลองรุ่นใหม่ล่าสุดในhttp://code.google.com/p/key-mon/เช่นการเขียนนี้มันเป็น keymon_1.17-1_all.deb 229 KB ปล่อยตัว 3 มกราคม 2014 สนับสนุน - สวิตช์เหนียวทดสอบและยืนยัน


1
นีซพบ แต่key-monการแสดงที่ปุ่มถูกกดและไม่ได้สถานะของปุ่มเครื่องปรับ ความแตกต่างก็คือkey-monจอแสดงผลที่จะยกเลิกกดรัฐ1 วินาทีหลังจากกดปุ่มนั้น แอปเพล็รัฐปรับปรุงแป้นพิมพ์จะกลับมาแสดงผลให้รัฐไม่ได้กดเมื่อกดปุ่มต่อไปจะเกิดขึ้นและดังนั้นจึงปิดการใช้งาน 'กด' รัฐ
dotancohen

คำตอบที่แก้ไขใหม่
เอ็ลเดอ

ขอโทษสำหรับความสับสน. ฉันได้แก้ไขคำตอบ (อีกครั้ง) เพื่อให้สิ่งที่คุณต้องการ
Elder Geek

1
ขอบคุณพี่ Geek --stickyตัวเลือกที่น่าจะคาดเดาสถานะของปุ่มปรับแต่งด้วยการดูสถานะคีย์อื่น ๆ แทนการสอบถามอินเตอร์เฟซที่เหมาะสมเช่นเดียวกับแป้นพิมพ์ที่เหมาะสม applets รัฐปรับปรุง สิ่งนี้สามารถเห็นได้โดยการกดปุ่มตัวดัดแปลงสองครั้ง: ครั้งแรกจะเปิดใช้งานตัวบ่งชี้ในแอปเพล็ต แต่ครั้งที่สองจะไม่ปล่อย ดังนั้นรัฐจะรายงานอย่างผิดพลาดว่ามีการใช้งานเมื่อมันไม่ได้ ข้อบกพร่องที่เกี่ยวข้องนี้แก้ไขปัญหาบางส่วนฉันจะกรอกรายละเอียดที่นั่นและในข้อบกพร่องเพิ่มเติม ขอขอบคุณ.
dotancohen

1
@dotancohen ฉันทดสอบตามข้อความของคุณว่า "แอปเพล็ตตัวดัดแปลงสถานะแป้นพิมพ์จะเปลี่ยนการแสดงผลกลับสู่สถานะที่ไม่มีการบีบอัดเมื่อมีการกดปุ่มครั้งต่อไปดังนั้นจึงปิดการใช้งานสถานะ 'กด' และมันก็ไม่เคยเกิดขึ้นกับฉันว่าใครจะกดปุ่มตัวปรับสองครั้งติดต่อกันตามวัตถุประสงค์ ฉันขอโทษสำหรับการกำกับดูแล
เอ็ลเดอ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.