#include "config.h" #include #include #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) typedef struct _client { gchar *name; Window win; gchar *msg; gchar *clientname; gchar *version; gchar *author; gchar *email; gchar *web; gchar *address; gchar *info; } Client; Client *e_client = NULL; static Window root_win = None; static Window comms_win = None; static Window my_win = None; static GdkWindow *gdkwin = NULL; static GdkWindow *gdkwin2 = NULL; static void (*msg_receive_callback) (gchar * msg) = NULL; static void CommsSetup(void); static GdkFilterReturn CommsFilter(GdkXEvent * gdk_xevent, GdkEvent * event, gpointer data); static Window CommsFindCommsWindow(void); static gchar *CommsGet(Client ** c, XEvent * ev); static Client *MakeClient(Window win); static void ListFreeClient(void *ptr); static gchar in_init = 0; gint CommsInit(void (*msg_receive_func) (gchar * msg)) { Window win; gchar st[32]; Client *cl; CommsSetup(); comms_win = win = CommsFindCommsWindow(); if (win == None) return 1; cl = MakeClient(win); g_snprintf(st, sizeof(st), "%8x", (int)win); cl->name = g_strdup(st); e_client = cl; gdkwin = gdk_window_foreign_new(win); gdk_window_add_filter(gdkwin, CommsFilter, NULL); gdkwin2 = gdk_window_foreign_new(my_win); gdk_window_add_filter(gdkwin2, CommsFilter, NULL); gdk_window_set_events(gdkwin, GDK_STRUCTURE_MASK); msg_receive_callback = msg_receive_func; return 0; } void CommsSend(const gchar * s) { gchar ss[21]; int i, j, k, len; XEvent ev; static Atom a = 0; Client *c; c = e_client; if ((!s) || (!c)) return; len = strlen(s); if (!a) a = gdk_x11_get_xatom_by_name("ENL_MSG"); ev.xclient.type = ClientMessage; ev.xclient.serial = 0; ev.xclient.send_event = True; ev.xclient.window = c->win; ev.xclient.message_type = a; ev.xclient.format = 8; for (i = 0; i < len + 1; i += 12) { g_snprintf(ss, sizeof(ss), "%8x", (int)my_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(gdk_x11_get_default_xdisplay(), c->win, False, 0, (XEvent *) & ev); } XFlush(gdk_x11_get_default_xdisplay()); } static GdkFilterReturn CommsFilter(GdkXEvent * gdk_xevent, GdkEvent * event __UNUSED__, gpointer data __UNUSED__) { XEvent *xevent; gchar *msg = NULL; Client *c = NULL; static Atom a; data = NULL; if (!a) a = gdk_x11_get_xatom_by_name("ENL_MSG"); xevent = (XEvent *) gdk_xevent; switch (xevent->type) { case DestroyNotify: if (xevent->xdestroywindow.window == comms_win) { gint i; comms_win = 0; if (!in_init) { for (i = 0; ((i < 20) && (!comms_win)); i++) { if ((comms_win = CommsFindCommsWindow())) { gchar st[256]; ListFreeClient(e_client); e_client = MakeClient(comms_win); g_snprintf(st, sizeof(st), "%8x", (int)comms_win); e_client->name = g_strdup(st); if (gdkwin) g_object_unref(gdkwin); gdkwin = gdk_window_foreign_new(comms_win); gdk_window_add_filter(gdkwin, CommsFilter, NULL); gdk_window_set_events(gdkwin, GDK_STRUCTURE_MASK); } sleep(1); } } if (!comms_win) { GtkWidget *win, *frame, *vbox, *label, *button; win = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_resizable(GTK_WINDOW(win), FALSE); gtk_window_set_position(GTK_WINDOW(win), GTK_WIN_POS_CENTER); frame = gtk_frame_new(NULL); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT); vbox = gtk_vbox_new(FALSE, 5); button = gtk_button_new_with_label("Bye bye!"); g_signal_connect(G_OBJECT(button), "clicked", on_exit_application, NULL); label = gtk_label_new("EEEEEEEEEEEEEEK! HELP! HEEEEEEEEEELP!\n" "\n" "Enlightenment disappeared on me!\n" "\n" "Someone help me - I'm drowning - drowning\n" "\n" "That's it. I'm out of here. I can't deal with the\n" "idea of losing Enlightenment. I'm going to jump and\n" "don't try and stop me.\n" "\n"); gtk_container_add(GTK_CONTAINER(win), frame); gtk_container_add(GTK_CONTAINER(vbox), vbox); gtk_container_set_border_width(GTK_CONTAINER(vbox), 32); gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0); gtk_widget_show_all(win); gtk_main(); exit(1); } } else { #if USE_GTK == 0 /* Needed? */ gdk_window_destroy_notify(((GdkEventAny *) event)->window); #endif } break; case ClientMessage: if (xevent->xclient.message_type != a) return GDK_FILTER_CONTINUE; msg = CommsGet(&c, xevent); if (msg) { if (msg_receive_callback) (*msg_receive_callback) (msg); g_free(msg); } break; default: break; } return GDK_FILTER_REMOVE; } static void CommsSetup(void) { char *str; str = getenv("ENL_WM_ROOT"); root_win = (str) ? strtoul(str, NULL, 0) : GDK_ROOT_WINDOW(); my_win = XCreateSimpleWindow(gdk_x11_get_default_xdisplay(), root_win, -100, -100, 5, 5, 0, 0, 0); } static Window CommsFindCommsWindow(void) { unsigned char *s; Atom a, ar; unsigned long num, after; int format; Window win = None; Window rt; int dint; unsigned int duint; a = gdk_x11_get_xatom_by_name("ENLIGHTENMENT_COMMS"); if (a == None) return None; s = NULL; XGetWindowProperty(gdk_x11_get_default_xdisplay(), root_win, a, 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 (gdk_x11_get_default_xdisplay(), win, &rt, &dint, &dint, &duint, &duint, &duint, &duint)) return None; s = NULL; XGetWindowProperty(gdk_x11_get_default_xdisplay(), win, a, 0, 14, False, AnyPropertyType, &ar, &format, &num, &after, &s); if (!s) return None; XFree(s); return win; } static gchar * CommsGet(Client ** c, XEvent * ev) { gchar s[13], s2[9], *msg; int i; Window win; Client *cl; static Atom a; if (!a) a = gdk_x11_get_xatom_by_name("ENL_MSG"); if ((!ev) || (!c)) return (NULL); if (ev->type != ClientMessage) return (NULL); if (ev->xclient.message_type != a) 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); cl = e_client; if (!cl) return (NULL); if (cl->msg) { /* append text to end of msg */ cl->msg = g_realloc(cl->msg, strlen(cl->msg) + strlen(s) + 1); if (!cl->msg) return (NULL); strcat(cl->msg, s); } else { /* new msg */ cl->msg = g_malloc(strlen(s) + 1); if (!cl->msg) return (NULL); strcpy(cl->msg, s); } if (strlen(s) < 12) { msg = cl->msg; cl->msg = NULL; *c = cl; } return (msg); } static Client * MakeClient(Window win) { Client *c; c = g_malloc0(sizeof(Client)); if (c) c->win = win; return c; } static void ListFreeClient(void *ptr) { Client *c; c = (Client *) ptr; if (!c) return; g_free(c->name); g_free(c->msg); g_free(c->clientname); g_free(c->version); g_free(c->author); g_free(c->email); g_free(c->web); g_free(c->address); g_free(c->info); g_free(c); }