[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: