My Gtk Tutorial 3

所谓的具体类的实现,其实这个Widget功能不得不说是Gtk里面缺少的功能,虽然其实Qt里面也没,不过我在写代码的时候可以没什么顾虑的用 KDE 提供的 UI 库,于是我又爽了。

这次的Widget就是一个捕获快捷键用的Widget,具体里面代码的实现我是当初从ccsm(compiz那个配置工具)里面的python代码翻译过来的,啊一想起那个青涩的年代……

相信这是个人民群众喜闻乐见的Widget。

原理很简单,本身是一个button,button按下时显示一个window,window负责捕捉按键,捕捉到的按键再存起来。

当然我的实现里面使用了一些Fcitx自己的parse和toString的函数,你当然建议使用GtkAccelerator的方式 来进行parse(如果你需要字符串的话)。

https://github.com/fcitx/fcitx-configtool/blob/master/gtk3/keygrab.h

https://github.com/fcitx/fcitx-configtool/blob/master/gtk3/keygrab.c

具体的实现就是上面的代码(于是我还看到当初有些蛋疼的注释……)

首先就是我继承了一个GtkButton,定义了一个Signal,触发按键在变化时的事件。

    gtk_widget_set_size_request(GTK_WIDGET(keygrabbutton), 150, -1);
    g_signal_connect(G_OBJECT(keygrabbutton), “clicked”, (GCallback) begin_key_grab, NULL);

按键创建时,绑了一个signal给clicked事件,用来显示一个popup。

在clicked里面的回调函数中。

    KeyGrabButton* b = KEYGRAB_BUTTON(self);
    b->popup = popup_new(GTK_WIDGET(self), _("Please press the new key combination"), FALSE);
    gtk_widget_add_events(GTK_WIDGET(b->popup), GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
    gtk_widget_show_all(b->popup);
    gtk_window_present(GTK_WINDOW(b->popup));
    b->handler = g_signal_connect(G_OBJECT(b->popup), "key-press-event", (GCallback)on_key_press_event, b);
    GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(b->popup));
    GdkDisplay* display = gdk_window_get_display (window);
    GdkDeviceManager* device_manager = gdk_display_get_device_manager (display);
    GdkDevice* pointer = gdk_device_manager_get_client_pointer (device_manager);
    GdkDevice* keyboard = gdk_device_get_associated_device (pointer);

    while (gdk_device_grab(
        keyboard,
        window,
        GDK_OWNERSHIP_WINDOW, TRUE,
        GDK_KEY_PRESS | GDK_KEY_RELEASE,
        NULL,
        GDK_CURRENT_TIME) != GDK_GRAB_SUCCESS)
        usleep(100);

进行了这样的操作,popup new中的实现其实很简单,就是弹出一个window,并且将其parent设置为顶层窗口,如果你的函数中需要使用dialog,或者设置为modal窗口的话,你会经常用到gtk_widget_get_toplevel,用于获得顶层的GtkWindow对象,参数就是任意一个已经在GtkWidget树中的Widget即可。

这里的grab事件的地方是非常tricky的,说实话也比gtk2的时候罗嗦了不少,不过大概的意思还是比较好懂,首先是要获得keyboard的GdkDevice指针,然后就是罗嗦个半天获得了,然后就是一个死循环,不断的尝试grab,事件呢则通过key-press-event传递给对应的window,里面 GDK_OWNERSHIP_WINDOW 就是指定了要grab 的事件是针对这个window的。后面的mask则是指定了要grab什么样的事件。这里就是key press和key release。

需要注意的就是,在最后还需要用  gdk_device_ungrab 来结束grab的影响。

P. S.

当然我写完也不会认为这样的文字有什么直接帮助,你觉得有什么帮助吗?我觉得没有,我写了这么久代码之后,我觉得只要给我文档,再没什么外力帮助下再写这些内容对我来说就像呼吸一样简单。一来我也不知道想要了解的人需要知道什么,因为编程本身就是一个自学成才的工作。如果你在大学学习学习过比如数据结构,算法设计等等课程,你可能也注意到了老师是从来不教给你具体编程的技巧的,如果妄图光是看着代码而不去实际尝试做点什么,你一定死得很惨。

有问题留言是欢迎的。

This entry was posted in Gtk. Bookmark the permalink.

One Response to My Gtk Tutorial 3

  1. yyc says:
    Google Chrome 19.0.1084.52 GNU/Linux x64

    看到了更加怨念的东西, 貌似gtkaccelerator是不兼容xkb-redirect的万恶之源啊~~~ (我又小众了)

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.