diff -Naur xxkb-1.10.orig/README.koi8 xxkb-1.10/README.koi8 --- xxkb-1.10.orig/README.koi8 2003-04-01 16:08:34.000000000 +0300 +++ xxkb-1.10/README.koi8 2005-10-02 13:41:44.000000000 +0300 @@ -91,10 +91,10 @@ сильно зависит от типа WM. XXkb.mainwindow.in_tray - сообщает GNOME или KDE, что xxkb должен встраиваться -в tray. Значение опции GNOME, KDE или KDE2, в зависимости от того, в чей tray -надо поместить xxkb. (К сожалению, такие docklet'ы имеют размер меньше, чем -размеры иконок для главного окна в дистрибутиве xxkb. Если хотите использовать -эту возможность, подберите подходящие иконки). +в tray. Значение опции GNOME, GNOME2, KDE или KDE2, в зависимости от того, в +чей tray надо поместить xxkb. (К сожалению, такие docklet'ы имеют размер +меньше, чем размеры иконок для главного окна в дистрибутиве xxkb. Если хотите +использовать эту возможность, подберите подходящие иконки). XXkb.mainwindow.geometry - размер главного окна - "ширина"x"высота" (желательно, чтобы они соответствовали размеру "картинок" для главного окна) diff -Naur xxkb-1.10.orig/XXkb.ad xxkb-1.10/XXkb.ad --- xxkb-1.10.orig/XXkb.ad 2002-12-05 07:02:04.000000000 +0200 +++ xxkb-1.10/XXkb.ad 2005-10-02 13:41:44.000000000 +0300 @@ -13,7 +13,7 @@ XXkb.mainwindow.xpm.4: ! XXkb.mainwindow.in_tray: -! possible values - KDE, KDE2, GNOME +! possible values - KDE, KDE2, GNOME, GNOME2 XXkb.button.enable: yes XXkb.button.geometry: 15x15-60+7 diff -Naur xxkb-1.10.orig/xxkb.c xxkb-1.10/xxkb.c --- xxkb-1.10.orig/xxkb.c 2003-03-19 14:56:06.000000000 +0200 +++ xxkb-1.10/xxkb.c 2005-10-02 15:14:27.000000000 +0300 @@ -1,6 +1,8 @@ /* xxkb - XKB keyboard indicator/switcher */ /* (c) 1999 - 2003 Ivan Pascal */ +#include +#include #include #include #include @@ -35,9 +37,21 @@ WInfo def_info, *info, *tmp_info; kbdState def_state; XFocusChangeEvent focused_event; + +struct { + Bool enable; + Atom tray_atom; + Atom opcode_atom; + Atom manager_atom; + Window manager; +} gnome2_tray; + XErrorHandler DefErrHandler; +static Bool trap_errors = False; +static int trapped_error_code = 0; static ListAction FindAppList(Window w); +static void Gnome2TrayUpdateManager(); int main (int argc, char ** argv) { @@ -148,6 +162,8 @@ } else icon = (Window) 0; + gnome2_tray.enable = False; + if (conf.tray_type) { Atom r; int data = 1; @@ -161,18 +177,35 @@ r = XInternAtom(dpy, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False); XChangeProperty(dpy, MainWin, r, XA_WINDOW, 32, 0, (unsigned char *)&data, 1); + } else if (! strcmp(conf.tray_type, "GNOME2")) { + char tmp[64]; + + size_hints = XAllocSizeHints(); + size_hints->width = size_hints->min_width = geom.width; + size_hints->height = size_hints->min_height = geom.height; + size_hints->flags = PSize | PMinSize; + XSetWMNormalHints(dpy, MainWin, size_hints); + + gnome2_tray.enable = True; + sprintf(tmp, "_NET_SYSTEM_TRAY_S%d", scr); + gnome2_tray.tray_atom = XInternAtom(dpy, tmp, False); + gnome2_tray.opcode_atom = XInternAtom(dpy, + "_NET_SYSTEM_TRAY_OPCODE", False); + gnome2_tray.manager_atom = XInternAtom(dpy, "MANAGER", False); } } + - - if (conf.controls&Main_enable) XMapWindow(dpy, MainWin); + if (conf.controls&Main_enable && ! gnome2_tray.enable) + XMapWindow(dpy, MainWin); /* What events we want */ XkbSelectEventDetails(dpy, XkbUseCoreKbd, XkbStateNotify, XkbAllStateComponentsMask, XkbGroupStateMask); - if (conf.controls&When_create) - XSelectInput(dpy, root, SubstructureNotifyMask); + XSelectInput(dpy, root, + ((conf.controls&When_create) ? SubstructureNotifyMask : NoEventMask) | + ((gnome2_tray.enable) ? StructureNotifyMask : NoEventMask)); XSelectInput(dpy, MainWin, ExposureMask | ButtonPressMask); if (icon) XSelectInput(dpy, icon, ExposureMask | ButtonPressMask); @@ -205,6 +238,8 @@ if (!info) info = &def_info; } + if (gnome2_tray.enable) Gnome2TrayUpdateManager(); + /* Main Loop */ while (1) { XNextEvent(dpy, &ev.core); @@ -391,6 +426,10 @@ if(((win == MainWin) || (win == icon)) && ev.core.xclient.data.l[0] == wm_del_win) Terminate(); + else if (gnome2_tray.enable && + ev.core.xclient.message_type == gnome2_tray.manager_atom && + ev.core.xclient.data.l[1] == gnome2_tray.tray_atom) + Gnome2TrayUpdateManager(); break; case CreateNotify: case UnmapNotify: @@ -758,9 +797,50 @@ } } -void ErrHandler(Display *dpy, XErrorEvent* err) +static void Gnome2TrayUpdateManager() { - if((err->error_code == BadWindow) || (err->error_code == BadDrawable)) - return; - (*DefErrHandler)(dpy, err); + gnome2_tray.manager = XGetSelectionOwner(dpy, + gnome2_tray.tray_atom); + + if (gnome2_tray.manager) + { + XClientMessageEvent xev; + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.window = gnome2_tray.manager; + xev.message_type = gnome2_tray.opcode_atom; + xev.format = 32; + xev.data.l[0] = CurrentTime; + xev.data.l[1] = 0; /* SYSTEM_TRAY_REQUEST_DOCK */ + xev.data.l[2] = MainWin; + + TrapErrors(); + XSendEvent(dpy, gnome2_tray.manager, False, NoEventMask, + (XEvent *) &xev); + UntrapErrors(); + } +} + +void TrapErrors() +{ + trapped_error_code = 0; + trap_errors = True; +} + +int UntrapErrors() +{ + trap_errors = False; + return trapped_error_code; +} + +int ErrHandler(Display *dpy, XErrorEvent* err) +{ + if (! trap_errors) { + if((err->error_code == BadWindow) || (err->error_code == BadDrawable)) + return 0; + (*DefErrHandler)(dpy, err); + } else { + trapped_error_code = err->error_code; + return 0; + } } diff -Naur xxkb-1.10.orig/xxkb.h xxkb-1.10/xxkb.h --- xxkb-1.10.orig/xxkb.h 2002-11-30 15:26:14.000000000 +0200 +++ xxkb-1.10/xxkb.h 2005-10-02 13:41:44.000000000 +0300 @@ -66,7 +66,9 @@ void Terminate(void); Bool ExpectInput(Window win); -void ErrHandler(Display* dpy, XErrorEvent* err); +int ErrHandler(Display* dpy, XErrorEvent* err); +void TrapErrors(); +int UntrapErrors(); WInfo* AddWindow(Window w, Window parent); void GetAppWindow(Window w, Window* app); diff -Naur xxkb-1.10.orig/xxkb.man xxkb-1.10/xxkb.man --- xxkb-1.10.orig/xxkb.man 2003-04-01 16:17:18.000000000 +0300 +++ xxkb-1.10/xxkb.man 2005-10-02 13:41:44.000000000 +0300 @@ -77,9 +77,10 @@ .TP 4 .B XXkb.mainwindow.in_tray allow to dock \fBxxkb\fR into a system tray. A value of the option should be -GNOME, KDE or KDE2 in depend on what environment tray you use. (Unfortunately, -such docklets have a size less than a default icons size for an xxkb main -window. If you want to use this option you need another set of icons.) +GNOME, GNOME2, KDE or KDE2 in depend on what environment tray you use. +(Unfortunately, such docklets have a size less than a default icons size for +an xxkb main window. If you want to use this option you need another set of +icons.) .TP 4 .B XXkb.mainwindow.geometry the geometry ( WIDTHxHEIGHT{+-}X{+-}Y ) of the main window.