GTK3功能键;哪些消耗(并且我的GTK应用程序无法使用)?

时间:2017-10-18 12:11:25

标签: linux gtk3

FWIW,激发这个问题的确切方案是(在Linux / Debian / Sid / x86-64上)my bismon在github上,提交d43a75fb9f8e13。 GTK3是3.22.24。如果您需要尝试,请使用make构建它并运行./bismon。它处于alpha阶段,对我来说仍然没有其他感兴趣。它是某种带有GTK接口和持久堆的DSL解释器。

如果您想要显示某些内容,请单击以关注中间窗口小部件,在其中键入the_system,然后键入 Ctrl Return ,但这与此问题无关。< / SUP>

我成功了,with commandview_BM(它是中间窗口小部件)是GtkTextView窗口小部件

g_signal_connect (commandview_BM, "key-press-event",
                G_CALLBACK (handlekeypresscmd_BM), NULL);

处理一些键盘事件(FWIW,我的物理键盘是AZERTY布局罗技G610)

我想在我的程序中处理功能键。但是一些功能键(例如 F7 F8 F9 F10 ...)被“抢先”桌面或环境,并没有到达我的程序。其他人到达,例如 F6 handlekeypresscmd_BM函数中提供debugging输出:

gui_BM.c:3135: handlekeypresscmd_BM keyval 0xffc3 KEY_F6 

这让我很开心(因为以后我可以编写有用的代码)。相关代码如下:

gboolean
handlekeypresscmd_BM (GtkWidget * widg, GdkEventKey * evk, gpointer data)
{
  assert (GTK_IS_TEXT_VIEW (widg));
  assert (evk != NULL);
  assert (data == NULL);
  if (evk->keyval == GDK_KEY_Return) { /* do something unrelated */ 
    return true; }
  else if (evk->keyval == GDK_KEY_Tab)
    {
      tabautocompletecmd_BM ();
      return true;
    }
  else if (evk->keyval >= GDK_KEY_F1 && evk->keyval <= GDK_KEY_F10)
    {
      GdkModifierType modmask = gtk_accelerator_get_default_mod_mask ();
      bool withctrl = (evk->state & modmask) == GDK_CONTROL_MASK;
      bool withshift = (evk->state & modmask) == GDK_SHIFT_MASK;
      DBGPRINTF_BM ("handlekeypresscmd_BM keyval %#x KEY_F%d %s%s",
                    evk->keyval, evk->keyval - (GDK_KEY_F1 - 1),
                    withctrl ? " ctrl" : "", withshift ? " shift" : "");
      return false;
  };
  return false;                 // propagate the event
}                               /* end handlekeypresscmd_BM */

显然应该为 F7 达到DBGPRINTF_BM(一些调试打印宏),而不仅仅是 F6 ,但它不是(我不是明白为什么)。当然,我检查了我的系统/usr/include/gtk-3.0/gdk/gdkkeysyms.h包含

#define GDK_KEY_F5 0xffc2
#define GDK_KEY_F6 0xffc3
#define GDK_KEY_F7 0xffc4
#define GDK_KEY_F8 0xffc5
#define GDK_KEY_F9 0xffc6

我正在使用Gnome,XFCE4或LXDE作为我的桌面环境。 AFAIK我没有专门针对功能键进行配置。

预定义的功能键列表(其他东西已经使用过的,可能是窗口管理器)是否可以访问和记录?哪里?我应该在ICCCCM的Gnome人机界面中查看EWMH,深入了解每个窗口管理器的文档吗?

更重要的是,有没有办法,从GTK3应用程序到 以编程方式查询某些小部件将到达哪些功能键(如GtkTextView我想不出任何......

或者,我合理地期望从Linux上的Gtk3应用程序(使用X11,以及稍后可能使用Wayland)使用的一小组功能键是什么?

FWIW,xev看到 F1 F12

的所有功能键

附加物

为了部分回答我的问题,gtk/gtktextview.c(来自GTK3的源代码)在第1630行附近:

  /* Caret mode */
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_F7, 0,
                "toggle-cursor-visible", 0);

(顺便说一句,是否有某种方法可以禁用它?)

但这并不能解释 F8 的行为,也不告诉我如何查询可以使用哪些功能键。

我的textview位于gtk/gtkpaned.c第635行

中的GtkPaned
  gtk_binding_entry_add_signal (binding_set,
                GDK_KEY_F8, 0,
                "cycle-handle-focus", 1,
                G_TYPE_BOOLEAN, FALSE);

所以也许我应该尝试找出如何查询这样的绑定键。仍然没有想法。应该调查GtkBindingSet

1 个答案:

答案 0 :(得分:2)

尝试分解您的问题,以便更容易回答。

首先,我建议您阅读The GTK+ Input and Event Handling Model并注意“ GTK +从窗口系统接收事件”。

  

我正在使用Gnome,XFCE4或LXDE作为我的桌面环境。   AFAIK我没有专门针对功能键进行配置。

嗯,除了“发行版”/窗口管理员之外,你没有。

例如,请检查GNOME Shell Keyboard shortcuts

大多数窗口管理器使用 ALT + Fn 键, ALT + F4 以关闭窗口而闻名。 CTRL 键更适合用户“快捷键/加速器”。

  

更重要的是,有没有办法,从GTK3应用程序到   以编程方式查询某些人将到达哪些功能键   小部件(像GtkTextView)?我想不出任何......

不,没有。发出/触发事件和小部件,如果编程这样做,则相应地接收和处理它们,然后通过检查事件,就像使用key-press-event处理程序一样,可以触发“动作”。好吧,从理论上讲,你可以在你自己的小部件中开发一组setter和getters处理键,但老实说,这并没有明白这一点。

  

或者,我合理地可以使用的一小组功能键是什么   期望在Linux上使用Gtk3应用程序(使用X11,也许还可以   后来与Wayland)?

我会去 CTRL + Fn SHIFT + Fn 和正常 F1 F12 离开 ALT + Fn 为Windowing系统保留。

现在查看Github上的具体示例,由于条件,您的处理程序已经忽略 F11 F12

...
... if (evk->keyval >= GDK_KEY_F1 && evk->keyval <= GDK_KEY_F10)
...

使用初始打印功能调整代码到控制台:

gboolean
handlekeypresscmd_BM (GtkWidget * widg, GdkEventKey * evk, gpointer data)
{
  assert (GTK_IS_TEXT_VIEW (widg));
  assert (evk != NULL);
  assert (data == NULL);

  if (evk->keyval >= GDK_KEY_F1 && evk->keyval <= GDK_KEY_F12) {
     g_print ("handlekeypresscmd_BM KEY_F%d\n", evk->keyval - (GDK_KEY_F1 - 1));
  }
  // see <gdk/gdkkeysyms.h> for names of keysyms
  if (evk->keyval == GDK_KEY_Return)
    {
      GdkModifierType modmask = gtk_accelerator_get_default_mod_mask ();
      bool withctrl = (evk->state & modmask) == GDK_CONTROL_MASK;
      bool withshift = (evk->state & modmask) == GDK_SHIFT_MASK;
      if (withctrl)
        run_then_erase_command_BM ();
      else if (withshift)
        run_then_keep_command_BM ();
      else                      // plain RETURN key, propagate it
        return false;
      return true;
    }
  else if (evk->keyval == GDK_KEY_Tab)
    {
      tabautocompletecmd_BM ();
      return true;
    }
  else if (evk->keyval >= GDK_KEY_F1 && evk->keyval <= GDK_KEY_F10)
    {
      GdkModifierType modmask = gtk_accelerator_get_default_mod_mask ();
      bool withctrl = (evk->state & modmask) == GDK_CONTROL_MASK;
      bool withshift = (evk->state & modmask) == GDK_SHIFT_MASK;
      DBGPRINTF_BM ("handlekeypresscmd_BM keyval %#x KEY_F%d %s%s",
                    evk->keyval, evk->keyval - (GDK_KEY_F1 - 1),
                    withctrl ? " ctrl" : "", withshift ? " shift" : "");
      return false;
    }
  return false;                 // propagate the event
}  

运行应用程序bismon并将焦点放在GtkTreeView上并按下几个 Fn 键和 CTRL + Fn 键后,结果为:< / p>

handlekeypresscmd_BM KEY_F1
gui_BM.c:3138: handlekeypresscmd_BM keyval 0xffbe KEY_F1 
handlekeypresscmd_BM KEY_F2
gui_BM.c:3138: handlekeypresscmd_BM keyval 0xffbf KEY_F2 
handlekeypresscmd_BM KEY_F3
gui_BM.c:3138: handlekeypresscmd_BM keyval 0xffc0 KEY_F3 
handlekeypresscmd_BM KEY_F4
gui_BM.c:3138: handlekeypresscmd_BM keyval 0xffc1 KEY_F4 
handlekeypresscmd_BM KEY_F5
gui_BM.c:3138: handlekeypresscmd_BM keyval 0xffc2 KEY_F5 
handlekeypresscmd_BM KEY_F6
gui_BM.c:3138: handlekeypresscmd_BM keyval 0xffc3 KEY_F6 
handlekeypresscmd_BM KEY_F7
gui_BM.c:3138: handlekeypresscmd_BM keyval 0xffc4 KEY_F7 
handlekeypresscmd_BM KEY_F8
gui_BM.c:3138: handlekeypresscmd_BM keyval 0xffc5 KEY_F8 
handlekeypresscmd_BM KEY_F9
gui_BM.c:3138: handlekeypresscmd_BM keyval 0xffc6 KEY_F9 
handlekeypresscmd_BM KEY_F11
handlekeypresscmd_BM KEY_F12
handlekeypresscmd_BM KEY_F1
gui_BM.c:3138: handlekeypresscmd_BM keyval 0xffbe KEY_F1  ctrl
handlekeypresscmd_BM KEY_F2
gui_BM.c:3138: handlekeypresscmd_BM keyval 0xffbf KEY_F2  ctrl
handlekeypresscmd_BM KEY_F3
gui_BM.c:3138: handlekeypresscmd_BM keyval 0xffc0 KEY_F3  ctrl
handlekeypresscmd_BM KEY_F4
gui_BM.c:3138: handlekeypresscmd_BM keyval 0xffc1 KEY_F4  ctrl
handlekeypresscmd_BM KEY_F5
gui_BM.c:3138: handlekeypresscmd_BM keyval 0xffc2 KEY_F5  ctrl
handlekeypresscmd_BM KEY_F6
gui_BM.c:3138: handlekeypresscmd_BM keyval 0xffc3 KEY_F6  ctrl
handlekeypresscmd_BM KEY_F7
gui_BM.c:3138: handlekeypresscmd_BM keyval 0xffc4 KEY_F7  ctrl
handlekeypresscmd_BM KEY_F8
gui_BM.c:3138: handlekeypresscmd_BM keyval 0xffc5 KEY_F8  ctrl
handlekeypresscmd_BM KEY_F9
gui_BM.c:3138: handlekeypresscmd_BM keyval 0xffc6 KEY_F9  ctrl
handlekeypresscmd_BM KEY_F10
gui_BM.c:3138: handlekeypresscmd_BM keyval 0xffc7 KEY_F10  ctrl
handlekeypresscmd_BM KEY_F11
handlekeypresscmd_BM KEY_F12

正如你所看到的, F10 没有显示,这是因为当使用GtkMenus时,F10被保留用于触发它们(请注意,在GNOME 3上,F10是为Gear Menu提出的,虽然没有硬编码就像在GtkMenuShell中一样)。 SHIFT + F10 也可用作ContextMenu键盘快捷键。

我也注意到你的应用程序 F6 SHIFT + F6 会将焦点移到GtkTreeView下面的小部件,不确定你是否自己编码但是不能在你的代码中找不到它的任何引用(下面是另一个例子)。 F8 也做了类似的事情,但是如果在每次按键之后你强行将焦点放在GtkTreeView上(用鼠标左键点击它),那么你将获得所有的按键操作。 CTRL + Fn 适用于所有密钥(您有解决方案)。

作为最后一个例子,使用来自zetcode的简单,适应的Treeview示例,您可以验证所有功能键,除了那些使用 ALT SHIFT + F10 (ContextMenu),工作:

#include <gtk/gtk.h>

gboolean
keyHandler (GtkWidget *widget,
               GdkEventKey  *event,
               gpointer   user_data) {
   if (event->keyval >= GDK_KEY_F1 && event->keyval <= GDK_KEY_F12) {
      GdkModifierType modmask = gtk_accelerator_get_default_mod_mask ();
      gboolean ctrl = (event->state & modmask) == GDK_CONTROL_MASK;
      gboolean shift = (event->state & modmask) == GDK_SHIFT_MASK;
      g_print ("HANDLED %s%sKEY_F%d\n", ctrl ? "CTRL+" : "", shift ? "SHIFT+" : "", event->keyval - (GDK_KEY_F1 - 1));
   }

   return FALSE;
}

int main(int argc, char *argv[]) {

  GtkWidget *window;
  GtkWidget *view;
  GtkWidget *vbox;

  GtkTextBuffer *buffer;
  GtkTextIter start, end;
  GtkTextIter iter;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
  gtk_window_set_title(GTK_WINDOW(window), "GtkTextView");

  vbox = gtk_vbox_new(FALSE, 0);
  view = gtk_text_view_new();
  gtk_box_pack_start(GTK_BOX(vbox), view, TRUE, TRUE, 0);

  buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));

  gtk_text_buffer_create_tag(buffer, "gap",
        "pixels_above_lines", 30, NULL);

  gtk_text_buffer_create_tag(buffer, "lmarg", 
      "left_margin", 5, NULL);
  gtk_text_buffer_create_tag(buffer, "blue_fg", 
      "foreground", "blue", NULL); 
  gtk_text_buffer_create_tag(buffer, "gray_bg", 
      "background", "gray", NULL); 
  gtk_text_buffer_create_tag(buffer, "italic", 
      "style", PANGO_STYLE_ITALIC, NULL);
  gtk_text_buffer_create_tag(buffer, "bold", 
      "weight", PANGO_WEIGHT_BOLD, NULL);

  gtk_text_buffer_get_iter_at_offset(buffer, &iter, 0);

  gtk_text_buffer_insert(buffer, &iter, "Plain text\n", -1);
  gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, 
        "Colored Text\n", -1, "blue_fg", "lmarg",  NULL);
  gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, 
        "Text with colored background\n", -1, "lmarg", "gray_bg", NULL);

  gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, 
        "Text in italics\n", -1, "italic", "lmarg",  NULL);

  gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, 
        "Bold text\n", -1, "bold", "lmarg",  NULL);

  gtk_container_add(GTK_CONTAINER(window), vbox);

  g_signal_connect(G_OBJECT(view), "key-press-event", G_CALLBACK(keyHandler), NULL);

  g_signal_connect(G_OBJECT(window), "destroy",
        G_CALLBACK(gtk_main_quit), NULL);

  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}

结果是(显示上下文菜单!):

screenshot

另请注意,应用程序没有菜单,因此处理F10时没有问题。

编辑:在快捷方式上查看此Wikipedia entry