如何通过GLib GDBus API获取GNOME Shell Eval方法返回结果?
解决GNOME Shell DBus Eval方法调用的问题
问题根源
你的代码存在两个核心错误,直接导致了CRITICAL断言失败:
- 对象路径格式错误:创建DBus代理时传入的
"/org/gnome/Shell/"末尾多了斜杠,DBus对象路径不允许以斜杠结尾,正确路径应为"/org/gnome/Shell"。 - 无效代理引发连锁错误:由于代理创建失败,后续
g_dbus_proxy_call_sync传入的proxy无效,返回的result为NULL,进而触发g_variant_get的断言错误。
此外,即使解决上述问题,Eval返回的字符串是JavaScript字面量格式(带转义引号),需要额外处理才能得到真实的窗口标题。
修正后的代码
#include <stdbool.h> #include <stdio.h> #include <glib/gprintf.h> #include <gio/gio.h> #include <string.h> void test_getwindows(GDBusProxy *proxy) { GError *error = NULL; g_printf("Calling Eval()...\n"); // 调用Eval方法,获取聚焦窗口标题的JS代码 GVariant *result = g_dbus_proxy_call_sync(proxy, "Eval", g_variant_new("s", "global.get_window_actors().find(actor => actor.meta_window.has_focus()).meta_window.get_title()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error != NULL) { g_printerr("调用失败: %s\n", error->message); g_error_free(error); return; } // 提取返回的成功状态和结果字符串 gboolean success; gchar *raw_title; g_variant_get(result, "(bs)", &success, &raw_title); if (success && raw_title != NULL) { // 处理JS字符串的转义:去掉前后引号,解析转义字符 gchar *window_title = NULL; if (strlen(raw_title) >= 2 && raw_title[0] == '"' && raw_title[strlen(raw_title)-1] == '"') { // 去掉首尾引号,解析转义序列 window_title = g_strcompress(raw_title + 1); // 截断结尾的引号 window_title[strlen(window_title)-1] = '\0'; } else { window_title = g_strdup(raw_title); } g_printf("window_title: %s\nsuccess: %d\n", window_title, success); g_free(window_title); } else { g_printf("获取窗口标题失败\nsuccess: %d\n", success); } g_free(raw_title); g_variant_unref(result); } int main(void) { GDBusProxy *proxy = NULL; GDBusConnection *conn = NULL; GError *error = NULL; // 获取会话总线连接 conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error); if (error != NULL) { g_printerr("获取总线连接失败: %s\n", error->message); g_error_free(error); return 1; } // 创建DBus代理:修正对象路径,去掉末尾斜杠 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL, "org.gnome.Shell", "/org/gnome/Shell", // 正确的对象路径 "org.gnome.Shell", NULL, &error); if (error != NULL) { g_printerr("创建代理失败: %s\n", error->message); g_error_free(error); g_object_unref(conn); return 1; } test_getwindows(proxy); // 释放资源 g_object_unref(proxy); g_object_unref(conn); return 0; }
关键修正点说明
- 对象路径规范:将
"/org/gnome/Shell/"改为"/org/gnome/Shell",符合DBus对象路径的语法要求。 - 错误处理增强:添加了对总线连接、代理创建、方法调用的错误检查,避免断言失败导致程序崩溃。
- 字符串转义处理:Eval返回的是JavaScript格式的字符串(如
"\"ibse@ibse-VirtualBox: ~\""),通过g_strcompress解析转义字符,并去掉首尾引号,得到真实的窗口标题。 - 资源管理:添加了
g_variant_unref、g_free和g_object_unref来正确释放GLib资源,避免内存泄漏。
编译与运行
使用以下命令编译(需安装GLib和GIO开发库):
gcc -o get_focused_window get_focused_window.c `pkg-config --cflags --libs glib-2.0 gio-2.0`
运行时需确保当前用户为桌面会话的活跃用户,以获得GNOME Shell DBus接口的访问权限。
内容的提问来源于stack exchange,提问作者ibse
相关产品推荐
相关产品推荐

