#include "config.h" #include #include #include #include #include #include #include "e16keyedit.h" #define gdk_window_foreign_new(xwin) \ gdk_x11_window_foreign_new_for_display(gdk_display_get_default(), xwin) #if USE_GTK == 3 #define gdk_error_trap_push() \ gdk_x11_display_error_trap_push(gdk_display_get_default()) #define gdk_error_trap_pop() \ gdk_x11_display_error_trap_pop(gdk_display_get_default()) #endif typedef struct { Window win; char *msg; #if 0 char *name; char *clientname; char *version; char *author; char *email; char *web; char *address; char *info; #endif } Client; static Display *dpy = NULL; static Window root_win = None; static Window comms_win = None; static Window my_msg_win = None; static Client *e_client = NULL; static void (*msg_receive_callback)(char *msg) = NULL; static unsigned int Atom_ENL_MSG; static int CommsSetup(void) { char *str; dpy = gdk_x11_get_default_xdisplay(); str = getenv("ENL_WM_ROOT"); root_win = (str) ? strtoul(str, NULL, 0) : DefaultRootWindow(dpy); gdk_error_trap_push(); my_msg_win = XCreateSimpleWindow(dpy, root_win, -10, -10, 1, 1, 0, 0, 0); XSync(dpy, False); if (gdk_error_trap_pop()) return 1; Atom_ENL_MSG = XInternAtom(dpy, "ENL_MSG", False); return 0; } static Window CommsFindCommsWindow(void) { unsigned char *s; Atom Atom_ENL_COMMS, ar; unsigned long num, after; int format; Window win = None; Window rt; int dint; unsigned int duint; Atom_ENL_COMMS = XInternAtom(dpy, "ENLIGHTENMENT_COMMS", True); if (Atom_ENL_COMMS == None) return None; s = NULL; XGetWindowProperty(dpy, root_win, Atom_ENL_COMMS, 0, 14, False, AnyPropertyType, &ar, &format, &num, &after, &s); if (s) { sscanf((char *)s, "%*s %x", (unsigned int *)&win); XFree(s); } if (win == None) return None; if (!XGetGeometry(dpy, win, &rt, &dint, &dint, &duint, &duint, &duint, &duint)) return None; s = NULL; XGetWindowProperty(dpy, win, Atom_ENL_COMMS, 0, 14, False, AnyPropertyType, &ar, &format, &num, &after, &s); if (!s) return None; XFree(s); return win; } static Client * ClientCreate(Window win) { Client *cl; cl = calloc(1, sizeof(Client)); if (!cl) return cl; cl->win = win; #if 0 char st[32]; snprintf(st, sizeof(st), "%8x", (int)win); cl->name = strdup(st); #endif return cl; } static char * CommsGet(XEvent *ev) { char buf[13], *msg; unsigned int win; Client *cl = e_client; if (!cl) return NULL; if (!ev) return NULL; if (ev->type != ClientMessage) return NULL; if (ev->xclient.message_type != Atom_ENL_MSG) return NULL; /* Message should start with comms_win but we don't check */ memcpy(buf, ev->xclient.data.b, 8); buf[8] = 0; sscanf(buf, "%x", &win); memcpy(buf, ev->xclient.data.b + 8, 12); buf[12] = 0; if (cl->msg) { /* append text to end of msg */ cl->msg = realloc(cl->msg, strlen(cl->msg) + strlen(buf) + 1); if (!cl->msg) return NULL; strcat(cl->msg, buf); } else { /* new msg */ cl->msg = malloc(strlen(buf) + 1); if (!cl->msg) return NULL; strcpy(cl->msg, buf); } msg = NULL; if (strlen(buf) < 12) { msg = cl->msg; cl->msg = NULL; } return msg; } static GdkFilterReturn FilterCommsWin(GdkXEvent *gdk_xevent, GdkEvent *event __UNUSED__, void *data __UNUSED__) { XEvent *xevent = gdk_xevent; switch (xevent->type) { default: break; case DestroyNotify: exit(1); } return GDK_FILTER_REMOVE; } static GdkFilterReturn FilterMyMsgWin(GdkXEvent *gdk_xevent, GdkEvent *event __UNUSED__, void *data __UNUSED__) { XEvent *xevent = gdk_xevent; char *msg; switch (xevent->type) { default: break; case ClientMessage: if (xevent->xclient.message_type != Atom_ENL_MSG) return GDK_FILTER_CONTINUE; msg = CommsGet(xevent); if (msg) { if (msg_receive_callback) (*msg_receive_callback) (msg); free(msg); } break; } return GDK_FILTER_REMOVE; } int CommsInit(void (*msg_receive_func)(char *msg)) { GdkWindow *gdkwin; if (CommsSetup()) return 1; comms_win = CommsFindCommsWindow(); if (comms_win == None) return 1; e_client = ClientCreate(comms_win); gdkwin = gdk_window_foreign_new(comms_win); gdk_window_set_events(gdkwin, GDK_STRUCTURE_MASK); gdk_window_add_filter(gdkwin, FilterCommsWin, NULL); gdkwin = gdk_window_foreign_new(my_msg_win); gdk_window_add_filter(gdkwin, FilterMyMsgWin, NULL); msg_receive_callback = msg_receive_func; return 0; } void CommsSend(const char *s) { char ss[21]; int i, j, k, len; XEvent ev; Client *cl = e_client; if (!s || !cl) return; len = strlen(s); ev.xclient.type = ClientMessage; ev.xclient.serial = 0; ev.xclient.send_event = True; ev.xclient.window = cl->win; ev.xclient.message_type = Atom_ENL_MSG; ev.xclient.format = 8; for (i = 0; i < len + 1; i += 12) { snprintf(ss, sizeof(ss), "%8x", (int)my_msg_win); for (j = 0; j < 12; j++) { ss[8 + j] = s[i + j]; if (!s[i + j]) j = 12; } ss[20] = 0; for (k = 0; k < 20; k++) ev.xclient.data.b[k] = ss[k]; XSendEvent(dpy, cl->win, False, 0, &ev); } XFlush(dpy); }