#include "config.h" #include #include #include #include #include "comms.h" #define EXID unsigned int static EXID comms_win = 0; static EXID my_win = 0; static EXID Atom_ENL_COMMS = 0; static EXID Atom_ENL_MSG = 0; static EXID _CommsFindCommsWindow(void) { unsigned char *s; Atom ar; unsigned long num, after; int format; EXID cwin; /* Get root window ENLIGHTENMENT_COMMS property */ cwin = 0; s = NULL; XGetWindowProperty(disp, root, Atom_ENL_COMMS, 0, 14, False, AnyPropertyType, &ar, &format, &num, &after, &s); if (!s) goto done; sscanf((char *)s, "%*s %x", &cwin); XFree(s); /* Check that cwin exists and has ENLIGHTENMENT_COMMS */ s = NULL; XGetWindowProperty(disp, cwin, Atom_ENL_COMMS, 0, 14, False, AnyPropertyType, &ar, &format, &num, &after, &s); if (!s) goto done; XFree(s); XSelectInput(disp, cwin, StructureNotifyMask | SubstructureNotifyMask); done: return cwin; } void CommsSetup(void) { if (Atom_ENL_COMMS == 0) Atom_ENL_COMMS = XInternAtom(disp, "ENLIGHTENMENT_COMMS", False); if (Atom_ENL_MSG == 0) Atom_ENL_MSG = XInternAtom(disp, "ENL_MSG", False); for (;;) { comms_win = _CommsFindCommsWindow(); if (comms_win != None) break; sleep(1); } if (!my_win) { my_win = XCreateWindow(disp, root, -10, -10, 1, 1, 0, CopyFromParent, InputOnly, CopyFromParent, 0, NULL); XSelectInput(disp, my_win, StructureNotifyMask | SubstructureNotifyMask); } } void CommsHandleDestroy(Window xwin) { if (xwin == comms_win) comms_win = 0; } int CommsHandlePropertyNotify(XEvent *ev) { if (comms_win) return 0; if (ev->xproperty.atom == Atom_ENL_COMMS) CommsSetup(); if (comms_win) return 1; return 0; } int CommsSend(const char *buf, unsigned int len) { char ss[21]; unsigned int i, j, k; XEvent ev; ev.xclient.type = ClientMessage; ev.xclient.serial = 0; ev.xclient.send_event = True; ev.xclient.window = comms_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_win); for (j = 0; j < 12; j++) { ss[8 + j] = buf[i + j]; if (!buf[i + j]) j = 12; } ss[20] = 0; for (k = 0; k < 20; k++) ev.xclient.data.b[k] = ss[k]; XSendEvent(disp, comms_win, False, 0, &ev); } return len; } static Bool ev_check(Display *d __UNUSED__, XEvent *ev, XPointer p __UNUSED__) { if (ev->type == ClientMessage) { if (ev->xclient.window == my_win) return True; } else if (ev->type == DestroyNotify) { if (ev->xdestroywindow.window == comms_win) return True; } return False; } char * CommsWaitForMessage(void) { XEvent ev; char *msg = NULL; for (;;) { XIfEvent(disp, &ev, ev_check, NULL); if (ev.type == DestroyNotify) { comms_win = 0; break; } else { msg = CommsHandleClientMessage(&ev); if (msg) break; } } return msg; } char * CommsHandleClientMessage(XEvent *ev) { char s[13], s2[9], *msg = NULL; int i; Window win = 0; static char *c_msg = NULL; if (!ev) return NULL; if (ev->type != ClientMessage) return NULL; s[12] = 0; s2[8] = 0; msg = NULL; for (i = 0; i < 8; i++) s2[i] = ev->xclient.data.b[i]; for (i = 0; i < 12; i++) s[i] = ev->xclient.data.b[i + 8]; sscanf(s2, "%x", (int *)&win); if (win == comms_win) { if (c_msg) { c_msg = realloc(c_msg, strlen(c_msg) + strlen(s) + 1); if (!c_msg) return NULL; strcat(c_msg, s); } else { c_msg = malloc(strlen(s) + 1); if (!c_msg) return NULL; strcpy(c_msg, s); } if (strlen(s) < 12) { msg = c_msg; c_msg = NULL; } } return msg; }