【问题标题】:Getting keyboard modifiers state using Gnome libs (GDK) fetches initial state only使用 Gnome 库 (GDK) 获取键盘修饰符状态仅获取初始状态
【发布时间】:2015-08-05 07:28:40
【问题描述】:

我正在尝试通过 gnome GDK 或 GTK 库获取当前键盘修饰符状态,以实现显示该状态的可访问性 gnome shell 扩展。

我知道如何使用 xlib 获取他们的状态,但 gnome gjs 没有完全绑定。

下面的代码只获取初始状态。它不会更新状态。

/*
 * compiling: gcc `pkg-config --cflags gdk-3.0` -o gdk_mod gdk_mod.c `pkg-config --libs gdk-3.0`
 */

#include <gdk/gdk.h>

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

    gdk_init(&argc, &argv);

    GdkDisplay * disp;
    disp = gdk_display_open(NULL);
    if (disp!=NULL) g_printf("display connected!\n");

    GdkKeymap * kmap;
    kmap = gdk_keymap_get_for_display(disp);

    guint state;
    state = gdk_keymap_get_modifier_state(kmap);
    g_printf("mod state: %x\n", state);

    while (1) {
        g_usleep(1000000);
        //kmap = gdk_keymap_get_for_display(disp);
        state = gdk_keymap_get_modifier_state(kmap);
        g_printf("mod state: %x\n", state);
    }

}

这是一个示例输出,CAPS 锁定处于活动状态,然后处于非活动状态,但没有变化:

$ ./gdk_mod 
display found!
mod state: 2
mod state: 2
mod state: 2
mod state: 2
mod state: 2
^C

目前使用的是 Kubuntu 15.04。

我的代码有什么问题?

【问题讨论】:

  • 您可能需要运行 GTK+ 事件循环才能使其工作。尝试将g_usleep() 循环更改为基于g_timeout_add()loop,使用gtk_init() 而不是gdk_init(),并运行gtk_main()
  • @andlabs ,您的方法非常有效。您能否发布一个答案。我会再等一会儿来接受它,因为我想gtk_main 循环调用了一些gdk 级别的函数来将事件从X 拉/更新到gdk 事件队列。如果这些函数存在,我可以修复我的原始代码并使用纯 GDK 保留它。
  • @andlabs ,您应该得到答案的荣誉和声誉。我写了一个只是为了记录我的解决方案。如果您复制该评论作为答案,我会接受。
  • 啊,我本来打算研究如何单独使用 GDK,但你自己想通了,所以我想这行得通。

标签: c gtk gnome gdk gnome-shell-extensions


【解决方案1】:

您需要运行 GTK+ 事件循环才能使其工作。事件循环是 GLib 的 主循环 的一部分。当您调用gtk_main() 时,将运行此主循环。我不知道它是轮询事件还是将事件推送给它,但它不会像你试图做的那样即时询问键盘状态。

设置 GDK 最简单的方法是通过 GTK+ 使用 gtk_init()gtk_main()。您可以单独使用GDK,但我不知道如何。您似乎已经想通了,这很有效。

而不是调用g_usleep(),这只会阻塞您的程序,您可以将定期超时挂接到主循环中。这是通过g_timeout_add() 完成的。传递给 g_timeout_add() 的函数返回一个布尔值,该值决定是否应该停止计时器,因此您不必担心重新安排函数,因为 GLib 会为您完成。

【讨论】:

    【解决方案2】:
    • 确实,正如 andlabs 在他的评论中所说,我需要一个事件循环。他建议使用 GTK gtk_init()gtk_main() 非常有效。

      /*
       * compiling: gcc `pkg-config --cflags gtk+-3.0` -o gtk_xkbmod3 gtk_xkbmod3.c `pkg-config --libs gtk+-3.0`
       */
      
      #include <gtk/gtk.h>
      
      static void update(GdkKeymap * kmap) {
          guint state;
          state = gdk_keymap_get_modifier_state(kmap);
          g_printf("%i\n", state);
      }
      
      int main (int argc, char **argv) {
      
          gtk_init(&argc, &argv);
      
          GdkKeymap * kmap;
          kmap = gdk_keymap_get_default();
      
          g_timeout_add_seconds(1, (GSourceFunc) update, kmap);
      
          gtk_main();
      
      }
      
    • 我还可以将 GDK 与 GLib GMainLoop 一起使用。

      /*
       * compiling: gcc `pkg-config --cflags gdk-3.0` -o gdk_xkbmod4 gdk_xkbmod4.c `pkg-config --libs gdk-3.0`
       */
      
      #include <gdk/gdk.h>
      
      GMainLoop *mainloop;
      
      static void update(GdkKeymap * kmap) {
          guint state;
          state = gdk_keymap_get_modifier_state(kmap);
          g_printf("%i\n", state);
      }
      
      int main (int argc, char **argv) {    
      
          gdk_init(&argc, &argv);
      
          GdkKeymap * kmap;
          kmap = gdk_keymap_get_default();
      
          g_timeout_add_seconds(1, (GSourceFunc) update, kmap);
      
          mainloop = g_main_loop_new(g_main_context_default(), FALSE);
          g_main_loop_run(mainloop);    
      }
      

    参考资料:

    【讨论】:

      猜你喜欢
      • 2014-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-04
      • 2016-06-23
      相关资源
      最近更新 更多