为什么 GTK2 的 gtk_widget_add_accelerator 有时不添加快捷方式?
Why does GTK2's gtk_widget_add_accelerator not add a shortcut sometimes?
我发现 gtk_widget_add_accelerator 无法间歇性工作。在 Ubuntu 16.04 上的 GTK2 应用程序 运行 上,有些菜单项有快捷方式,有些则没有。我安装了符号和源以查看发生了什么,gtk_widget_add_accelerator 中的信号检查失败:
g_signal_query (g_signal_lookup (accel_signal, G_OBJECT_TYPE (widget)), &query);
if (!query.signal_id ||
!(query.signal_flags & G_SIGNAL_ACTION) ||
query.return_type != G_TYPE_NONE ||
query.n_params)
{
/* hmm, should be elaborate enough */
g_warning (G_STRLOC ": widget `%s' has no activatable signal \"%s\" without arguments",
G_OBJECT_TYPE_NAME (widget), accel_signal);
return;
}
所以我将该代码块复制到调用 gtk_widget_add_accelerator 之前,例如 this:
const char *Signal = "activate";
GSignalQuery query;
g_signal_query (g_signal_lookup (Signal, G_OBJECT_TYPE (w)), &query);
if (!stricmp(Sc, "Ctrl+C")) // This is the short cut that doesn't work
{
if (!query.signal_id)
printf("Bad sig id\n");
else if (!(query.signal_flags & G_SIGNAL_ACTION))
printf("No sig act\n");
else if (query.return_type != G_TYPE_NONE)
printf("Ret type err\n");
else if (query.n_params)
printf("Param err.\n");
else
printf("Pre-cond ok.\n");
}
gtk_widget_add_accelerator( w,
Signal,
Menu->AccelGrp,
GtkKey,
mod,
Gtk::GTK_ACCEL_VISIBLE
);
并打印 'Pre-cond ok.' 这意味着在我的应用程序级别有一个有效信号,但在 GTK2 库中没有。那么是否存在构建问题?不匹配 headers? IDK.
所以我开始准确地查看我正在构建的内容。 make file 使用这些标志:
Libs = \
-lmagic \
-static-libgcc \
`pkg-config --libs gtk+-2.0`
Inc = \
-I./include/common \
-I./include/linux/Gtk \
-I/usr/include/gstreamer-1.0 \
-I/usr/lib/x86_64-linux-gnu/gstreamer-1.0/include \
`pkg-config --cflags gtk+-2.0` \
-Iinclude/common \
-Iinclude/linux \
-Iinclude/linux/Gtk
看起来很标准,对吧?
所以我有点不知道为什么这不起作用。有什么想法吗?
作为参考,这是创建信号的代码:
Info = GTK_MENU_ITEM(gtk_menu_item_new_with_mnemonic(Txt));
Gtk::gulong ret = Gtk::g_signal_connect_data(Info,
"activate",
(Gtk::GCallback) MenuItemCallback,
this,
NULL,
Gtk::G_CONNECT_SWAPPED);
以及我的应用中 'query' 的内容:
(gdb) p query
= {signal_id = 132, signal_name = 0x7ffff76c4859 "activate",
itype = 17714704,
signal_flags = (Gtk::G_SIGNAL_RUN_FIRST | Gtk::G_SIGNAL_ACTION),
return_type = 4, n_params = 0, param_types = 0x0}
当我进入 GTK2 库时:
(gdb) p query
= {signal_id = 132, signal_name = 0x7ffff76c4859 "activate",
itype = 17714704, signal_flags = (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
return_type = 4, n_params = 0, param_types = 0x0}
但它只会在 g_warning 行之后到达那个阶段。也许这是由于编译器优化所致。
好的。似乎 Gtk 的调试符号让我走上了错误的道路。我从源代码构建并安装了 GTK2,它好多了。
gtk_widget_add_accelerator 实际上是在做正确的事情,而不是陷入信号错误处理程序。真正的问题是,当我将项目转换为也支持图标的项目时,我正在用 LgiMenuItem::Icon 中的另一个对象替换菜单项。这将删除我之前添加的加速器。当所有丢失的加速器都有图标时,我注意到了这一点。
所以"solution"就是将菜单项转为支持图标后重新添加快捷方式。也许接下来我会重构代码以提高效率,但此时我很高兴它能正常工作。
我发现 gtk_widget_add_accelerator 无法间歇性工作。在 Ubuntu 16.04 上的 GTK2 应用程序 运行 上,有些菜单项有快捷方式,有些则没有。我安装了符号和源以查看发生了什么,gtk_widget_add_accelerator 中的信号检查失败:
g_signal_query (g_signal_lookup (accel_signal, G_OBJECT_TYPE (widget)), &query);
if (!query.signal_id ||
!(query.signal_flags & G_SIGNAL_ACTION) ||
query.return_type != G_TYPE_NONE ||
query.n_params)
{
/* hmm, should be elaborate enough */
g_warning (G_STRLOC ": widget `%s' has no activatable signal \"%s\" without arguments",
G_OBJECT_TYPE_NAME (widget), accel_signal);
return;
}
所以我将该代码块复制到调用 gtk_widget_add_accelerator 之前,例如 this:
const char *Signal = "activate";
GSignalQuery query;
g_signal_query (g_signal_lookup (Signal, G_OBJECT_TYPE (w)), &query);
if (!stricmp(Sc, "Ctrl+C")) // This is the short cut that doesn't work
{
if (!query.signal_id)
printf("Bad sig id\n");
else if (!(query.signal_flags & G_SIGNAL_ACTION))
printf("No sig act\n");
else if (query.return_type != G_TYPE_NONE)
printf("Ret type err\n");
else if (query.n_params)
printf("Param err.\n");
else
printf("Pre-cond ok.\n");
}
gtk_widget_add_accelerator( w,
Signal,
Menu->AccelGrp,
GtkKey,
mod,
Gtk::GTK_ACCEL_VISIBLE
);
并打印 'Pre-cond ok.' 这意味着在我的应用程序级别有一个有效信号,但在 GTK2 库中没有。那么是否存在构建问题?不匹配 headers? IDK.
所以我开始准确地查看我正在构建的内容。 make file 使用这些标志:
Libs = \
-lmagic \
-static-libgcc \
`pkg-config --libs gtk+-2.0`
Inc = \
-I./include/common \
-I./include/linux/Gtk \
-I/usr/include/gstreamer-1.0 \
-I/usr/lib/x86_64-linux-gnu/gstreamer-1.0/include \
`pkg-config --cflags gtk+-2.0` \
-Iinclude/common \
-Iinclude/linux \
-Iinclude/linux/Gtk
看起来很标准,对吧?
所以我有点不知道为什么这不起作用。有什么想法吗?
作为参考,这是创建信号的代码:
Info = GTK_MENU_ITEM(gtk_menu_item_new_with_mnemonic(Txt));
Gtk::gulong ret = Gtk::g_signal_connect_data(Info,
"activate",
(Gtk::GCallback) MenuItemCallback,
this,
NULL,
Gtk::G_CONNECT_SWAPPED);
以及我的应用中 'query' 的内容:
(gdb) p query
= {signal_id = 132, signal_name = 0x7ffff76c4859 "activate",
itype = 17714704,
signal_flags = (Gtk::G_SIGNAL_RUN_FIRST | Gtk::G_SIGNAL_ACTION),
return_type = 4, n_params = 0, param_types = 0x0}
当我进入 GTK2 库时:
(gdb) p query
= {signal_id = 132, signal_name = 0x7ffff76c4859 "activate",
itype = 17714704, signal_flags = (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
return_type = 4, n_params = 0, param_types = 0x0}
但它只会在 g_warning 行之后到达那个阶段。也许这是由于编译器优化所致。
好的。似乎 Gtk 的调试符号让我走上了错误的道路。我从源代码构建并安装了 GTK2,它好多了。
gtk_widget_add_accelerator 实际上是在做正确的事情,而不是陷入信号错误处理程序。真正的问题是,当我将项目转换为也支持图标的项目时,我正在用 LgiMenuItem::Icon 中的另一个对象替换菜单项。这将删除我之前添加的加速器。当所有丢失的加速器都有图标时,我注意到了这一点。
所以"solution"就是将菜单项转为支持图标后重新添加快捷方式。也许接下来我会重构代码以提高效率,但此时我很高兴它能正常工作。