Re: IceWM tray bug (Was: Re: icewm + kaffeine)
On Tue, Oct 13, 2009 at 11:48:55AM +0700, Vladislav Naumov wrote:
> 2009/10/13 Eduard Bloch <blade@master.debian.org>:
> > Так вот в чем и вся проблема. Я не люблю быстрые хаки, такие действия без
> > соглассия апстреама приводят зачастую к проблемам, затяжньм ссорам и.т.п. К
> > сожеалению он гдето пропадает последие несколько месяцев. А у меня тоже нет
> > много свободного времени.
>
> Эдуард, со свободным временем у всех плохо.
> Точнее, у всех, кто может чего-то действительно исправить.
> Я попробую ещё поразбираться, конечно.
Владислав, вот плод моих вчерашних размышлений: программа, которая
умеет встраиваться во внутренний трей icewm и не вываливается из него
при рестарте. Демонстрирует то, как оно работает "внутрях".
Может, тебя это наведет на какую-нибудь мысль.
Всё, убег работать.
PS: gcc tray.c -lX11 -o tray
--
Stanislav
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <X11/Xlib.h>
#define SYSTEM_TRAY_REQUEST_DOCK 0
#define XEMBED_EMBEDDED_NOTIFY 0
Display *dpy;
Window win;
int black, white;
Atom _XEMBED, _XEMBED_INFO,
_ICEWM_INTTRAY_S0,
_NET_SYSTEM_TRAY_OPCODE,
_NET_SYSTEM_TRAY_S0;
void send_client_message(
Display* dpy, /* display */
Window w, /* receiver */
Atom message_type, /* message type */
long message, /* message opcode */
long data1, /* message data 1 */
long data2, /* message data 2 */
long data3 /* message data 3 */)
{
XEvent ev;
memset(&ev, 0, sizeof(ev));
ev.xclient.type = ClientMessage;
ev.xclient.window = w;
ev.xclient.message_type = message_type;
ev.xclient.format = 32;
ev.xclient.data.l[0] = CurrentTime;
ev.xclient.data.l[1] = message;
ev.xclient.data.l[2] = data1;
ev.xclient.data.l[3] = data2;
ev.xclient.data.l[4] = data3;
XSendEvent(dpy, w, False, NoEventMask, &ev);
}
void request_dock(void)
{
Window w = XGetSelectionOwner(dpy, _ICEWM_INTTRAY_S0);
send_client_message(dpy, w, _NET_SYSTEM_TRAY_OPCODE, SYSTEM_TRAY_REQUEST_DOCK, win, 0, 0);
}
Bool process_event(XEvent *xev)
{
switch (xev->type)
{
case ClientMessage:
if (xev->xclient.message_type == _XEMBED)
{
if (xev->xclient.data.l[1] == XEMBED_EMBEDDED_NOTIFY)
fprintf(stderr, "XEMBED_EMBEDDED_NOTIFY: window: %#lx, embedder = %#lx, protocol = %#lx\n",
xev->xclient.window, xev->xclient.data.l[3], xev->xclient.data.l[4]);
}
/* icewm notifies the systray about a restart by sending a message to the root window */
else if (xev->xclient.message_type == _ICEWM_INTTRAY_S0)
{
fprintf(stderr, "_NET_SYSTEM_TRAY_S0: send_event: %d, win: %#lx\n",
xev->xclient.send_event, xev->xclient.window);
request_dock();
}
break;
case ConfigureNotify:
fprintf(stderr, "ConfigureNotify: event: %#x, win: %#x, x = %d, y = %d, width = %d, height = %d\n",
xev->xconfigure.event, xev->xconfigure.window,
xev->xconfigure.x, xev->xconfigure.y,
xev->xconfigure.width, xev->xconfigure.height);
break;
case ReparentNotify:
fprintf(stderr, "ReparentNotify: event: %#x, win: %#x, parent = %#x, x = %d, y = %d\n",
xev->xreparent.event, xev->xreparent.window, xev->xreparent.parent,
xev->xreparent.x, xev->xreparent.y);
break;
case Expose:
if (xev->xexpose.count == 0)
{
XWindowAttributes attr;
GC gc = XCreateGC(xev->xexpose.display, xev->xexpose.window, 0, NULL);
XGetWindowAttributes(xev->xexpose.display, xev->xexpose.window, &attr);
XSetForeground(xev->xexpose.display, gc, black);
XFillRectangle(xev->xexpose.display, xev->xexpose.window,
gc, 0, 0, attr.width, attr.height);
XSetForeground(xev->xexpose.display, gc, white);
XDrawLine(xev->xexpose.display, xev->xexpose.window,
gc, 0, 0, attr.width, attr.height);
XDrawLine(xev->xexpose.display, xev->xexpose.window,
gc, 0, attr.height, attr.width, 0);
XFreeGC(xev->xexpose.display, gc);
}
break;
case DestroyNotify:
return False;
}
return True;
}
int main()
{
XEvent xev;
long data[2];
dpy = XOpenDisplay(":0.0");
black = BlackPixel(dpy, DefaultScreen(dpy));
white = WhitePixel(dpy, DefaultScreen(dpy));
_XEMBED = XInternAtom(dpy, "_XEMBED", False);
_XEMBED_INFO = XInternAtom(dpy, "_XEMBED_INFO", False);
_NET_SYSTEM_TRAY_OPCODE = XInternAtom (dpy, "_NET_SYSTEM_TRAY_OPCODE", False);
_NET_SYSTEM_TRAY_S0 = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False);
_ICEWM_INTTRAY_S0 = XInternAtom(dpy, "_ICEWM_INTTRAY_S0", False);
win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 20, 20, 1, black, black);
XSelectInput(dpy, win, StructureNotifyMask | ExposureMask);
/* we want to receive messages sent to the root window */
XSelectInput(dpy, DefaultRootWindow(dpy), StructureNotifyMask);
data[0] = 0; data[1] = 1;
XChangeProperty(dpy, win, _XEMBED_INFO, _XEMBED_INFO, 32, PropModeReplace, (char *)data, 2);
XSetSelectionOwner(dpy, _NET_SYSTEM_TRAY_S0, win, CurrentTime);
XMapWindow(dpy, win);
request_dock();
do
XNextEvent(dpy, &xev);
while (process_event(&xev));
XCloseDisplay(dpy);
return 0;
}
Reply to: