c - 在没有 GTK/QT 的 Linux 中创建系统托盘图标
问题描述
我需要使用纯粹的 Xlib 为我的应用程序创建一个托盘图标。经过一番搜索,阅读了 XEmbed 文档和一些关于 SO 的内容,这就是代码目前的样子(主要是复制和粘贴)。我理解它的作用,但不知道为什么。它在外观上创建了一个托盘图标,但在我的 mate-panels 区域中只有 1px 宽。我究竟做错了什么?为什么它不是普通托盘图标的大小?
这是我的代码:
#include <X11/Xutil.h>
#include <string.h>
#define MIN(A, B) ((A) < (B) ? (A) : (B))
/* --------- XEMBED and systray stuff */
#define SYSTEM_TRAY_REQUEST_DOCK 0
#define SYSTEM_TRAY_BEGIN_MESSAGE 1
#define SYSTEM_TRAY_CANCEL_MESSAGE 2
static int trapped_error_code = 0;
static int (*old_error_handler) (Display *, XErrorEvent *);
static int
error_handler(Display *display, XErrorEvent *error) {
trapped_error_code = error->error_code;
return 0;
}
void
trap_errors(void) {
trapped_error_code = 0;
old_error_handler = XSetErrorHandler(error_handler);
}
int
untrap_errors(void) {
XSetErrorHandler(old_error_handler);
return trapped_error_code;
}
void
send_systray_message(Display* dpy, long message, long data1, long data2, long data3) {
XEvent ev;
Atom selection_atom = XInternAtom (dpy,"_NET_SYSTEM_TRAY_S0",False);
Window tray = XGetSelectionOwner (dpy,selection_atom);
if ( tray != None)
XSelectInput (dpy,tray,StructureNotifyMask);
memset(&ev, 0, sizeof(ev));
ev.xclient.type = ClientMessage;
ev.xclient.window = tray;
ev.xclient.message_type = XInternAtom (dpy, "_NET_SYSTEM_TRAY_OPCODE", False );
ev.xclient.format = 32;
ev.xclient.data.l[0] = CurrentTime;
ev.xclient.data.l[1] = message;
ev.xclient.data.l[2] = data1; // <--- your window is only here
ev.xclient.data.l[3] = data2;
ev.xclient.data.l[4] = data3;
trap_errors();
XSendEvent(dpy, tray, False, NoEventMask, &ev);
XSync(dpy, False);
usleep(10000);
if (untrap_errors()) {
/* Handle errors */
}
}
/* ------------ Regular X stuff */
int
main(int argc, char **argv) {
int width, height;
XWindowAttributes wa;
XEvent ev;
Display *dpy;
int screen;
Window root, win;
/* init */
if (!(dpy=XOpenDisplay(NULL)))
return 1;
screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen);
if(!XGetWindowAttributes(dpy, root, &wa))
return 1;
width = height = MIN(wa.width, wa.height);
/* create window */
win = XCreateSimpleWindow(dpy, root, 0, 0, width, height, 0, 0, 0x7F7F997F);
send_systray_message(dpy, SYSTEM_TRAY_REQUEST_DOCK, win, 0, 0); // pass win only once
XMapWindow(dpy, win);
XSync(dpy, False);
/* run */
while(1) {
while(XPending(dpy)) {
XNextEvent(dpy, &ev); /* just waiting until we error because window closed */
}
}
}
我感谢所有能够为我指明正确方向的东西,即使它只是一些我目前还没有找到的文档。
解决方案
推荐阅读
- r - 使用 R 抓取数据 - POST 中带有列表的表单
- java - Hbox 不适合网格窗格中的行
- c# - 我有一个代码必须让我能够通过手指触摸移动 2d 游戏对象,但它不起作用,我该如何解决?
- ruby-on-rails - 按用户组计算付款的最有效方法
- python - 在python中附加数据框
- r - 当我编织到 pdf 时,我的图表和图像没有按照我的代码块在 Rmd 文件中的顺序出现
- reactjs - 父文件夹内的映射文件夹
- python-3.x - 如何修复 Python 3.x 中的“Alpr”对象没有属性“已加载”错误
- python - 开放CV 4 | 没有模块名称 cv2.cv2 |
- python - Matplotlib:箭袋图中只有线条