在没有 GTK/QT 的 Linux 中创建系统托盘图标

问题描述 投票:0回答:1

我需要纯粹使用 Xlib 为我的应用程序创建一个托盘图标。经过一番搜索、阅读 XEmbed 文档和 SO 上的一些内容后,这就是到目前为止代码的样子(主要是复制和粘贴)。我明白它的作用,但不明白为什么。它看起来正在创建一个托盘图标,但在我的伴侣面板区域中只有 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 */
        }
    }
}

我很感谢一切能够为我指明正确方向的东西,即使它只是我到目前为止还没有找到的一些文档。

c linux x11 xlib
1个回答
0
投票

系统托盘管理器将停靠您的托盘窗口并调整其大小。 只需将

Resize
X11 事件添加到窗口事件掩码并处理它们。 您也不应该使用根窗口大小作为初始大小,因为这太大了。

© www.soinside.com 2019 - 2024. All rights reserved.