diff options
| author | Dana Jansens <danakj@orodu.net> | 2003-08-01 05:00:23 +0000 |
|---|---|---|
| committer | Dana Jansens <danakj@orodu.net> | 2003-08-01 05:00:23 +0000 |
| commit | 759565a70e9bdd9bb842533f1c01df792d0bd1a4 (patch) | |
| tree | 885ba4ed1f01c57eedd12c13ad04bacaea0ff1f1 /tools/kdetrayproxy | |
| parent | 12a4cc4cbe382a36ab255676816b9e8bbe457c6b (diff) | |
add the kdetrayproxy tool
Diffstat (limited to 'tools/kdetrayproxy')
| -rw-r--r-- | tools/kdetrayproxy/.cvsignore | 4 | ||||
| -rw-r--r-- | tools/kdetrayproxy/Makefile | 4 | ||||
| -rw-r--r-- | tools/kdetrayproxy/kdetrayproxy.c | 220 |
3 files changed, 228 insertions, 0 deletions
diff --git a/tools/kdetrayproxy/.cvsignore b/tools/kdetrayproxy/.cvsignore new file mode 100644 index 00000000..3e53acde --- /dev/null +++ b/tools/kdetrayproxy/.cvsignore @@ -0,0 +1,4 @@ +.deps +.dirstamp +.libs +kdetrayproxy diff --git a/tools/kdetrayproxy/Makefile b/tools/kdetrayproxy/Makefile new file mode 100644 index 00000000..cfc46539 --- /dev/null +++ b/tools/kdetrayproxy/Makefile @@ -0,0 +1,4 @@ +all clean install: + $(MAKE) -C ../.. -$(MAKEFLAGS) $@ + +.PHONY: all clean install diff --git a/tools/kdetrayproxy/kdetrayproxy.c b/tools/kdetrayproxy/kdetrayproxy.c new file mode 100644 index 00000000..31a4d974 --- /dev/null +++ b/tools/kdetrayproxy/kdetrayproxy.c @@ -0,0 +1,220 @@ +#include <X11/Xlib.h> +#include <X11/Xatom.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/select.h> +#include <unistd.h> + +typedef struct IList { + Window win; + int ignore_unmaps; + + struct IList *next; +} IList; + +Display *display; +Window root; +Atom winhint; +Atom roothint; +int xfd; +IList *list; + +void init(); +void eventloop(); +void handleevent(XEvent *e); +void addicon(Window win); +void removeicon(Window win, int unmap); +int issystray(Atom *a, int n); +void updatehint(); +Window findclient(Window win); +int ignore_errors(Display *d, XErrorEvent *e); +void wait_time(unsigned int t); + +int main() +{ + init(); + updatehint(); + eventloop(); + return 0; +} + +void init() +{ + display = XOpenDisplay(NULL); + if (!display) { + fprintf(stderr, "Could not open display\n"); + exit(EXIT_FAILURE); + } + + xfd = ConnectionNumber(display); + + root = RootWindowOfScreen(DefaultScreenOfDisplay(display)); + + winhint = XInternAtom(display, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", 0); + roothint = XInternAtom(display, "_KDE_NET_SYSTEM_TRAY_WINDOWS", 0); + + XSelectInput(display, root, SubstructureNotifyMask); +} + +void eventloop() +{ + XEvent e; + fd_set set; + + while (1) { + int event = False; + while (XPending(display)) { + event = True; + XNextEvent(display, &e); + handleevent(&e); + } + if (!event) { + FD_ZERO(&set); + FD_SET(xfd, &set); + select(xfd + 1, &set, NULL, NULL, NULL); + } + } +} + +void handleevent(XEvent *e) +{ + switch (e->type) { + case MapNotify: + { + Atom *a; + int n; + Window w; + + w = findclient(e->xmap.window); + if (w) { + a = XListProperties(display, w, &n); + if (issystray(a, n)) + addicon(w); + XFree(a); + } + break; + } + case UnmapNotify: + removeicon(e->xunmap.window, True); + break; + case DestroyNotify: + removeicon(e->xdestroywindow.window, False); + break; + } +} + +int ignore_errors(Display *d, XErrorEvent *e) +{ + (void)d; (void)e; + return 1; +} + +void addicon(Window win) +{ + IList *it; + + for (it = list; it; it = it->next) + if (it->win == win) return; /* duplicate */ + + it = list; + list = malloc(sizeof(IList)); + list->win = win; + list->ignore_unmaps = 2; + list->next = it; + + XSelectInput(display, win, StructureNotifyMask); + /* if i set the root hint too fast the dock app can fuck itself up */ + wait_time(1000000 / 8); + updatehint(); +} + +void removeicon(Window win, int unmap) +{ + IList *it, *last = NULL; + void *old; + + for (it = list; it; last = it, it = it->next) + if (it->win == win) { + if (it->ignore_unmaps && unmap) { + it->ignore_unmaps--; + return; + } + + if (!last) + list = it->next; + else + last->next = it->next; + + XSync(display, False); + old = XSetErrorHandler(ignore_errors); + XSelectInput(display, win, NoEventMask); + XSync(display, False); + XSetErrorHandler(old); + free(it); + + updatehint(); + } +} + +int issystray(Atom *a, int n) +{ + int i, r = False; + + for (i = 0; i < n; ++i) { + if (a[i] == winhint) { + r = True; + break; + } + } + return r; +} + +void updatehint() +{ + IList *it; + int *wins, n, i; + + for (it = list, n = 0; it; it = it->next, ++n) ; + if (n) { + wins = malloc(sizeof(int) * n); + for (it = list, i = 0; it; it = it->next, ++i) + wins[i] = it->win; + } + XChangeProperty(display, root, roothint, XA_WINDOW, 32, PropModeReplace, + (unsigned char*) wins, n); +} + +Window findclient(Window win) +{ + Window r, *children; + unsigned int n, i; + Atom state = XInternAtom(display, "WM_STATE", True); + Atom ret_type; + int ret_format; + unsigned long ret_items, ret_bytesleft; + unsigned long *prop_return; + + XQueryTree(display, win, &r, &r, &children, &n); + for (i = 0; i < n; ++i) { + Window w = findclient(children[i]); + if (w) return w; + } + + /* try me */ + XGetWindowProperty(display, win, state, 0, 1, + False, state, &ret_type, &ret_format, + &ret_items, &ret_bytesleft, + (unsigned char**) &prop_return); + if (ret_type == None || ret_items < 1) + return None; + return win; /* found it! */ +} + +void wait_time(unsigned int t) +{ + struct timeval time; + time.tv_sec = 0; + time.tv_usec = t; + select(1, NULL, NULL, NULL, &time); +} |
