Làm cách nào để thêm một applet trạng thái sửa đổi bàn phím vào bảng Unity?


18

Tôi là người dùng KDE nghĩ về việc chuyển sang Unity. Do khuyết tật thủ công, tôi sử dụng các phím dính và trong KDE, tôi có một applet trong bảng hệ thống cho biết các phím bổ trợ nào đang hoạt động. Tôi nhớ rằng Gnome cũng có tính năng này, Windows và OS X cũng vậy.

Làm thế nào để một quảng cáo applet trạng thái sửa đổi bàn phím đến bảng điều khiển trong Unity?

Làm rõ: Tôi đã kích hoạt các phím dính. Tôi đang hỏi làm thế nào để thêm một applet cho biết trạng thái của các phím bổ trợ . Chỉ báo này sẽ hiển thị khi phím Shift bị ấn xuống, khi phím Alt bị ấn xuống, khi phím Thục bị ấn xuống và khi phím Ctrl bị ấn xuống. Applet này tồn tại trong tất cả các môi trường máy tính để bàn chính (KDE, Windows, Mac OSX và Gnome). Nó là cần thiết cho khả năng tiếp cận của máy tính để bàn.

Dưới đây là hình ảnh của applet trạng thái sửa đổi bàn phím, bên cạnh applet chỉ báo bố trí bàn phím. Các từ bổ nghĩa đại diện là, từ trái sang phải, Shift, Ctrl, Alt, I-dont-know-this-one, Tux/Win, NumLock, và CapsLock. Có thể thấy rằng phím NumLock đang hoạt động.

nhập mô tả hình ảnh ở đây


Errr ... Dường như có một khoảng trống lớn khi nói đến điều này ... Có một điều gì đó sẽ là tiếng bíp khi nhấn phím bổ trợ.
Wilf

@wilf Nếu tôi không nhầm có biểu tượng Trợ năng trong Unity (giống như Gnome 3) nhưng không phải là biểu tượng "phụ" để thông báo cho người dùng về trạng thái.
Braiam

4
@Takkat: Cảm ơn bạn đã gợi ý. indicator-keylockchỉ hiển thị tình trạng của những phím mà theo truyền thống có chỉ số trạng thái trên bàn phím chính nó: CapsLock, ScrollLock, NumLock. Tôi cần một chỉ số mà hiển thị trạng thái của các phím modifier tiêu chuẩn: Shift, Ctrl, Tux, Alt. Tất cả các máy tính để bàn chính (KDE, Windows, Mac OSX) đều có sẵn applet chỉ báo này.
dotancohen

1
Tôi tin rằng tên gói của công cụ KDE mà bạn đang đề cập cũng vậy plasma-widget-kbstatevà một tìm kiếm nhanh trong trung tâm phần mềm thực sự không chú ý đến bất kỳ kết quả tương đương nào
Daniel W.

2
@ Thắng: Tôi đang sử dụng plasmoid KB State. Nếu bạn đang sử dụng Kubfox, hãy cài đặt nó sudo apt-get install plasma-widget-kbstate.
dotancohen

Câu trả lời:


7

Đây là một vấn đề nổi bật trong Unity:

Mã dưới đây đã được cập nhật, bây giờ nó có thể sử dụng các biểu tượng để hiển thị trạng thái. Nhưng đôi khi nó có thể bị chậm vì tôi phải cập nhật tệp biểu tượng trên ổ cứng sau đó tải lại. (Xem ghi chú về vấn đề này / giới hạn trong libappindicator)

Một bản phát hành được đóng gói tốt đã được cung cấp trên webupd8 ppa (Cảm ơn Alin Andrei / Andrew /)

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

Tham khảo: Bộ điều chỉnh bàn phím Chỉ báo trạng thái cho Ubuntu: Chỉ báo Xkbmod


Câu trả lời gốc:

Đây không phải là một câu trả lời kinh điển cho câu hỏi. Nó có thể được tính là một công việc xung quanh. Hy vọng ai đó viết giải pháp tinh vi cho nó.

Đây là một chỉ báo sửa đổi bàn phím nguyên mẫu đơn giản cho Unity.

Hình ảnh bắt đầu từ bên trái: Biểu tượng, Shift, Caps Caps, Ctrl, Alt, Super, AltGr bị khóa (Vòng tròn nhỏ để biểu thị trạng thái bị khóa)

ảnh chụp màn hình của nguyên mẫu unity-xkbmod

Nguồn tập tin 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. Cài đặt các tiêu đề / libs cần thiết: (Không chắc chắn nếu tôi bỏ lỡ bất kỳ)

    sudo apt-get install libx11-dev libappindicator-dev libgtk2.0-dev
    
  2. Biên dịch:

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

    ./unity-xkbmod
    

Ghi chú:

  • libappindicatorđược sử dụng cho các chỉ số Unity thiếu một tính năng quan trọng giúp dễ dàng chuyển các chỉ số máy tính để bàn khác. Xem API lỗi # 812067 cần thiết: hỗ trợ cài đặt biểu tượng pixbuf

    Không có tính năng này, giả sử chúng ta cần (Shift, Ctrl, Alt, AltGr, Super) với các phím dính hoạt động; chúng tôi có 3 trạng thái chính cho mỗi trạng thái (Tắt, Bật / Đã khóa, Đã khóa). Vì vậy, 3 ^ 5 biểu tượng kết hợp nên được tạo ra. (Trường hợp bình thường chỉ có 3x5 biểu tượng đơn)

    Đó là lý do tại sao tôi sử dụng nhãn chỉ báo với các ký hiệu từ phông chữ DejaVu Sans .

  • Để đặt một biểu tượng, đặt nó trong cùng một thư mục và đặt tên cho nó icon.*. Các định dạng được chấp nhận: png, svg, ico, xpm ...

    Nếu bạn không thích bất kỳ biểu tượng nào, chỉ cần tạo hình ảnh 1x1 px.

Người giới thiệu:


Rất vui, cảm ơn bạn! Tôi sẽ thử cái này và lấy lại cho bạn. Tuyệt vời, Sneetsher!
dotancohen

Đó là bạn sneetsher!
dotancohen

vâng, cảm ơn bạn @dotancohen. Vì vậy, ít nhất bạn có thể sử dụng Unity, có thể nó xấu xí nếu không có biểu tượng vị trí cố định?
user.dz

1
Tôi không phiền, bạn sẽ thấy một hình ảnh của tôi! Tôi đã đề cập đến vấn đề này trên trình sửa lỗi Ubuntu .
dotancohen

1
Sneetsher, tôi muốn nói cảm ơn một lần nữa. Bây giờ tôi đã chuyển đến Unity và việc di chuyển sẽ là không thể nếu không có ứng dụng tuyệt vời này. Tôi cũng đã học được khá nhiều từ mã. Cảm ơn bạn!
dotancohen

2

Một giải pháp khác không hoàn hảo, nhưng một số có thể thấy nó hữu ích vì có thể có đầy đủ chức năng như trong KDE như kích hoạt một mod bằng một cú nhấp chuột.

  1. cài đặt kbstateapplet

    sudo apt-get install plasma-widget-kbstate kde-workspace-bin
    
  2. Chạy nó trong trình plasma-windowedphát

    • Cửa sổ thông thường

      plasma-windowed kbstate
      

      ảnh chụp màn hình của plasma-widget-kbstate trong Xubfox

    • Cửa sổ không biên giới

      plasma-windowed --noborder kbstate
      

      ảnh chụp màn hình của plasma-widget-kbstate không biên giới trong Unity

Tôi không có nhiều thời gian để chơi, nhưng wmctrlcó thể giúp định vị, thay đổi kích thước và đưa nó lên hàng đầu khi ra mắt.

Tham khảo: Lệnh nào để khởi động một plasmoid kde và menu kickstart


1

Tôi đã thực hiện tìm kiếm màn hình khóa dính Ubuntu và tìm thấy thứ gì đó có thể hữu ích ở đây: http://code.google.com.vn/p/key-mon/

hiển thị ảnh chụp màn hình trường hợp

Hãy thử chạy

key-mon --sticky Hỗ trợ cho các phím dính.

Tham khảo: http://code.google.com.vn/p/key-mon/

Lưu ý rằng phiên bản có sẵn thông qua trung tâm phần mềm là 1.6-0ubfox1. Được phát hành vào tháng 6 năm 2011 không hỗ trợ chuyển đổi --sticky. Nếu chỉ báo trông giống hệt như ở trên, bạn có phiên bản cũ hơn Hãy thử phiên bản mới nhất tại http://code.google.com.vn/p/key-mon/ khi viết bài này, đó là keymon_1.17-1_all.deb 229 KB Đã phát hành Ngày 3 tháng 1 năm 2014. Hỗ trợ cho --sticky switch đã được thử nghiệm và xác nhận.


1
Tìm thấy tốt, tuy nhiên key-moncho thấy nút nào được nhấn và không phải là trạng thái của các phím bổ trợ . Điểm khác biệt là key-monmàn hình sẽ trở về trạng thái chưa nhấn 1 giây sau khi nhấn nút . Một applet trạng thái sửa đổi bàn phím sẽ đưa màn hình về trạng thái không nhấn khi nhấn phím tiếp theo sẽ xảy ra và do đó vô hiệu hóa trạng thái 'nhấn' .
dotancohen

chỉnh sửa lại câu trả lời.
Anh Cả Geek

Xin lỗi vì sự nhầm lẫn. Tôi đã chỉnh sửa câu trả lời (một lần nữa) để cung cấp chính xác những gì bạn cần.
Anh Cả Geek

1
Cảm ơn Anh Cả. Các --stickytùy chọn dường như đoán trạng thái của các phím modifier bằng cách quan sát các phím khác nhà nước, thay vì truy vấn giao diện thích hợp cũng như bàn phím thích hợp applet nhà nước sửa đổi. Điều này có thể được nhìn thấy bằng cách nhấn phím bổ trợ hai lần: lần đầu tiên bật chỉ báo trong applet, nhưng lần thứ hai không giải phóng nó. Do đó, nhà nước được báo cáo sai là hoạt động khi không. Lỗi liên quan này giải quyết vấn đề một phần, tôi sẽ điền vào các chi tiết ở đó và các lỗi bổ sung. Cảm ơn bạn.
dotancohen

1
@dotancohen Tôi đã kiểm tra dựa trên tuyên bố của bạn rằng "Một applet trạng thái sửa đổi bàn phím sẽ đưa màn hình trở về trạng thái không nhấn khi nhấn phím tiếp theo sẽ xảy ra và do đó vô hiệu hóa trạng thái 'nhấn'." và tôi không bao giờ nhận ra rằng bất kỳ ai cũng sẽ nhấn phím bổ trợ hai lần liên tiếp. Tôi xin lỗi vì sự giám sát.
Anh Cả Geek
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.