You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

360 lines
8.4 KiB

#include "config.h"
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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"
11 years ago
"\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);
}