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。
答案 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;
}
结果是(显示上下文菜单!):
另请注意,应用程序没有菜单,因此处理F10时没有问题。
编辑:在快捷方式上查看此Wikipedia entry