scx/c/xlib/event.c

370 lines
11 KiB
C

#include "xlib.h"
#include "scheme48.h"
#define ECAST(name, type) type* name = (type*)e
#define sidx 4
#define SET(i, v) S48_VECTOR_SET(r, i, v)
#define SETSIZE(i) r = s48_make_vector(sidx+i, S48_FALSE)
s48_value scx_enter_event(XEvent* e) {
s48_value r = S48_FALSE;
s48_value temp = S48_FALSE;
int i;
S48_DECLARE_GC_PROTECT(2);
S48_GC_PROTECT_2(r, temp);
switch (e->type) {
case KeyPress : case KeyRelease :
case ButtonPress : case ButtonRelease :
case MotionNotify : {
ECAST(q, XKeyEvent);
SETSIZE(10);
// all equal in the beginning
SET(sidx+0, SCX_ENTER_WINDOW(q->root));
SET(sidx+1, SCX_ENTER_WINDOW(q->subwindow));
SET(sidx+2, SCX_ENTER_TIME(q->time));
SET(sidx+3, s48_enter_integer(q->x));
SET(sidx+4, s48_enter_integer(q->y));
SET(sidx+5, s48_enter_integer(q->x_root));
SET(sidx+6, s48_enter_integer(q->y_root));
SET(sidx+7, Bits_To_Symbols(q->state, State_Syms));
// now they are different
switch (e->type) {
case KeyPress : case KeyRelease : {
SET(sidx+8, s48_enter_integer(q->keycode));
SET(sidx+9, S48_ENTER_BOOLEAN(q->same_screen));
} break;
case ButtonPress : case ButtonRelease : {
ECAST(q, XButtonEvent);
SET(sidx+8, Bit_To_Symbol(q->button, Button_Syms));
SET(sidx+9, S48_ENTER_BOOLEAN(q->same_screen));
} break;
case MotionNotify : {
ECAST(q, XMotionEvent);
SET(sidx+8, S48_ENTER_BOOLEAN(q->is_hint));
SET(sidx+9, S48_ENTER_BOOLEAN(q->same_screen));
} break;
}
} break;
case EnterNotify : case LeaveNotify : {
ECAST(q, XCrossingEvent);
SETSIZE(12);
SET(sidx+0, SCX_ENTER_WINDOW(q->root));
SET(sidx+1, SCX_ENTER_WINDOW(q->subwindow));
SET(sidx+2, SCX_ENTER_TIME(q->time));
SET(sidx+3, s48_enter_integer(q->x));
SET(sidx+4, s48_enter_integer(q->y));
SET(sidx+5, s48_enter_integer(q->x_root));
SET(sidx+6, s48_enter_integer(q->y_root));
SET(sidx+7, Bit_To_Symbol(q->mode, Cross_Mode_Syms));
SET(sidx+8, Bit_To_Symbol(q->detail, Cross_Detail_Syms));
SET(sidx+9, S48_ENTER_BOOLEAN(q->same_screen));
SET(sidx+10, S48_ENTER_BOOLEAN(q->focus));
// Elk does this; but why not State_Syms??
SET(sidx+11, Bit_To_Symbol(q->state, Button_Syms));
} break;
case FocusIn : case FocusOut : {
ECAST(q, XFocusChangeEvent);
SETSIZE(2);
SET(sidx+0, Bit_To_Symbol(q->mode, Cross_Mode_Syms));
SET(sidx+1, Bit_To_Symbol(q->detail, Focus_Detail_Syms));
} break;
case KeymapNotify : {
ECAST(q, XKeymapEvent);
SETSIZE(1);
temp = s48_make_string(32, (char)0);
for (i=0; i < 32; i++)
S48_STRING_SET(temp, i, q->key_vector[i]);
SET(sidx+0, temp);
} break;
case Expose : {
ECAST(q, XExposeEvent);
SETSIZE(5);
SET(sidx+0, s48_enter_integer(q->x));
SET(sidx+1, s48_enter_integer(q->y));
SET(sidx+2, s48_enter_integer(q->width));
SET(sidx+3, s48_enter_integer(q->height));
SET(sidx+4, s48_enter_integer(q->count));
} break;
case GraphicsExpose : {
ECAST(q, XGraphicsExposeEvent);
SETSIZE(7);
// the ->window member is only a drawable here! ??
SET(sidx+0, s48_enter_integer(q->x));
SET(sidx+1, s48_enter_integer(q->y));
SET(sidx+2, s48_enter_integer(q->width));
SET(sidx+3, s48_enter_integer(q->height));
SET(sidx+4, s48_enter_integer(q->count));
SET(sidx+5, s48_enter_integer(q->major_code));
SET(sidx+6, s48_enter_integer(q->minor_code));
} break;
case NoExpose : {
ECAST(q, XNoExposeEvent);
SETSIZE(2);
SET(sidx+0, s48_enter_integer(q->major_code));
SET(sidx+1, s48_enter_integer(q->minor_code));
} break;
case VisibilityNotify : {
ECAST(q, XVisibilityEvent);
SETSIZE(1);
SET(sidx+0, Bit_To_Symbol(q->state, Visibility_Syms));
} break;
case CreateNotify : {
ECAST(q, XCreateWindowEvent);
SETSIZE(7);
SET(sidx+0, SCX_ENTER_WINDOW(q->window));
SET(sidx+1, s48_enter_integer(q->x));
SET(sidx+2, s48_enter_integer(q->y));
SET(sidx+3, s48_enter_integer(q->width));
SET(sidx+4, s48_enter_integer(q->height));
SET(sidx+5, s48_enter_integer(q->border_width));
SET(sidx+6, S48_ENTER_BOOLEAN(q->override_redirect));
} break;
case DestroyNotify : {
ECAST(q, XDestroyWindowEvent);
SETSIZE(1);
SET(sidx+0, SCX_ENTER_WINDOW(q->window));
} break;
case UnmapNotify : {
ECAST(q, XUnmapEvent);
SETSIZE(2);
SET(sidx+0, SCX_ENTER_WINDOW(q->window));
SET(sidx+1, S48_ENTER_BOOLEAN(q->from_configure));
} break;
case MapNotify : {
ECAST(q, XMapEvent);
SETSIZE(2);
SET(sidx+0, SCX_ENTER_WINDOW(q->window));
SET(sidx+1, S48_ENTER_BOOLEAN(q->override_redirect));
} break;
case MapRequest : {
ECAST(q, XMapRequestEvent);
SETSIZE(1);
SET(sidx+0, SCX_ENTER_WINDOW(q->window));
} break;
case ReparentNotify : {
ECAST(q, XReparentEvent);
SETSIZE(5);
SET(sidx+0, SCX_ENTER_WINDOW(q->window));
SET(sidx+1, SCX_ENTER_WINDOW(q->parent));
SET(sidx+2, s48_enter_integer(q->x));
SET(sidx+3, s48_enter_integer(q->y));
SET(sidx+4, S48_ENTER_BOOLEAN(q->override_redirect));
} break;
case ConfigureNotify : {
ECAST(q, XConfigureEvent);
SETSIZE(8);
SET(sidx+0, SCX_ENTER_WINDOW(q->window));
SET(sidx+1, s48_enter_integer(q->x));
SET(sidx+2, s48_enter_integer(q->y));
SET(sidx+3, s48_enter_integer(q->width));
SET(sidx+4, s48_enter_integer(q->height));
SET(sidx+5, s48_enter_integer(q->border_width));
SET(sidx+6, SCX_ENTER_WINDOW(q->above));
SET(sidx+7, S48_ENTER_BOOLEAN(q->override_redirect));
} break;
case ConfigureRequest : {
ECAST(q, XConfigureRequestEvent);
SETSIZE(9);
SET(sidx+0, SCX_ENTER_WINDOW(q->window));
SET(sidx+1, s48_enter_integer(q->x));
SET(sidx+2, s48_enter_integer(q->y));
SET(sidx+3, s48_enter_integer(q->width));
SET(sidx+4, s48_enter_integer(q->height));
SET(sidx+5, s48_enter_integer(q->border_width));
SET(sidx+6, SCX_ENTER_WINDOW(q->above));
SET(sidx+7, Bit_To_Symbol(q->detail, Stack_Mode_Syms));
SET(sidx+8, s48_enter_integer(q->value_mask));
} break;
case GravityNotify : {
ECAST(q, XGravityEvent);
SETSIZE(3);
SET(sidx+0, SCX_ENTER_WINDOW(q->window));
SET(sidx+1, s48_enter_integer(q->x));
SET(sidx+2, s48_enter_integer(q->y));
} break;
case ResizeRequest : {
ECAST(q, XResizeRequestEvent);
SETSIZE(2);
SET(sidx+0, s48_enter_integer(q->width));
SET(sidx+1, s48_enter_integer(q->height));
} break;
case CirculateRequest : {
ECAST(q, XCirculateEvent);
SETSIZE(2);
SET(sidx+0, SCX_ENTER_WINDOW(q->window));
SET(sidx+1, Bit_To_Symbol(q->place, Place_Syms));
} break;
case PropertyNotify : {
ECAST(q, XPropertyEvent);
SETSIZE(3);
SET(sidx+0, SCX_ENTER_ATOM(q->atom));
SET(sidx+1, SCX_ENTER_TIME(q->time));
SET(sidx+2, Bit_To_Symbol(q->state, Prop_Syms));
} break;
case SelectionClear : {
ECAST(q, XSelectionClearEvent);
SETSIZE(2);
SET(sidx+0, SCX_ENTER_ATOM(q->selection));
SET(sidx+1, SCX_ENTER_TIME(q->time));
} break;
case SelectionRequest : {
ECAST(q, XSelectionRequestEvent);
SETSIZE(5);
SET(sidx+0, SCX_ENTER_WINDOW(q->requestor));
SET(sidx+1, SCX_ENTER_ATOM(q->selection));
SET(sidx+2, SCX_ENTER_ATOM(q->target));
SET(sidx+3, SCX_ENTER_ATOM(q->property));
SET(sidx+4, SCX_ENTER_TIME(q->time));
} break;
case SelectionNotify : {
ECAST(q, XSelectionEvent);
SETSIZE(4);
SET(sidx+0, SCX_ENTER_ATOM(q->selection));
SET(sidx+1, SCX_ENTER_ATOM(q->target));
SET(sidx+2, SCX_ENTER_ATOM(q->property));
SET(sidx+3, SCX_ENTER_TIME(q->time));
} break;
case ColormapNotify : {
ECAST(q, XColormapEvent);
SETSIZE(3);
SET(sidx+0, SCX_ENTER_COLORMAP(q->colormap));
SET(sidx+1, S48_ENTER_BOOLEAN(q->new));
SET(sidx+2, q->state == ColormapInstalled ? S48_TRUE : S48_FALSE);
} break;
case ClientMessage : {
ECAST(q, XClientMessageEvent);
SETSIZE(2);
SET(sidx+0, SCX_ENTER_ATOM(q->message_type));
switch (q->format) {
case 8 : {
temp = s48_make_string(20, (char)0);
for (i=0; i < 20; i++)
S48_STRING_SET(temp, i, q->data.b[i]);
} break;
case 16 : {
temp = s48_make_vector(10, S48_FALSE);
for (i=0; i < 10; i++)
S48_VECTOR_SET(temp, i, s48_enter_integer(q->data.s[i]));
} break;
case 32 : {
temp = s48_make_vector(5, S48_FALSE);
for (i=0; i < 5; i++)
S48_VECTOR_SET(temp, i, s48_enter_integer(q->data.l[i]));
} break;
default : temp = s48_enter_integer(q->format); //??
}
SET(sidx+1, temp);
}
case MappingNotify : {
ECAST(q, XMappingEvent);
SETSIZE(3);
SET(sidx+0, Bit_To_Symbol(q->request, Mapping_Syms));
SET(sidx+1, s48_enter_integer(q->first_keycode));
SET(sidx+2, s48_enter_integer(q->count));
} break;
} // switch end
// XAnyEvent entries
{
ECAST(q, XAnyEvent);
SET(0, s48_enter_integer(q->serial));
SET(1, S48_ENTER_BOOLEAN(q->send_event));
SET(2, SCX_ENTER_DISPLAY(q->display));
SET(3, SCX_ENTER_WINDOW(q->window));
}
// more??
// And the Event-Name
r = s48_cons( Bit_To_Symbol(e->type, Event_Syms), r );
S48_GC_UNPROTECT();
return r;
}
s48_value scx_Next_Event(s48_value Xdisplay) {
XEvent e;
XNextEvent(SCX_EXTRACT_DISPLAY(Xdisplay), &e);
return scx_enter_event(&e);
}
s48_value scx_Peek_Event(s48_value Xdisplay) {
XEvent e;
XPeekEvent(SCX_EXTRACT_DISPLAY(Xdisplay), &e);
return scx_enter_event(&e);
}
s48_value scx_Events_Pending(s48_value Xdisplay) {
return s48_enter_integer(XPending(SCX_EXTRACT_DISPLAY(Xdisplay)));
}
s48_value scx_Get_Motion_Events(s48_value Xdisplay, s48_value Xwindow,
s48_value from, s48_value to) {
int n,i;
XTimeCoord *p = XGetMotionEvents(SCX_EXTRACT_DISPLAY(Xdisplay),
SCX_EXTRACT_WINDOW(Xwindow),
SCX_EXTRACT_TIME(from),
SCX_EXTRACT_TIME(to),
&n);
s48_value v = s48_make_vector(n, S48_FALSE);
s48_value l = S48_NULL;
S48_DECLARE_GC_PROTECT(2);
S48_GC_PROTECT_2(v,l);
for (i = 0; i < n; i++) {
l = s48_cons(SCX_ENTER_TIME(p[i].time),
s48_cons(s48_enter_integer(p[i].x),
s48_cons(s48_enter_integer(p[i].y), S48_NULL)));
S48_VECTOR_SET(v, i, l);
}
S48_GC_UNPROTECT();
XFree((char*)p);
return v;
}
s48_value scx_add_pending_channel (channel){
int socket_fd;
S48_CHECK_CHANNEL(channel);
socket_fd = S48_UNSAFE_EXTRACT_FIXNUM(S48_UNSAFE_CHANNEL_OS_INDEX(channel));
if (! s48_add_pending_fd(socket_fd, 1)) // 1 for: yes, is input
s48_raise_out_of_memory_error();
return S48_UNSPECIFIC;
}
void scx_init_event(void) {
S48_EXPORT_FUNCTION(scx_Next_Event);
S48_EXPORT_FUNCTION(scx_Peek_Event);
S48_EXPORT_FUNCTION(scx_Events_Pending);
S48_EXPORT_FUNCTION(scx_Get_Motion_Events);
S48_EXPORT_FUNCTION(scx_add_pending_channel);
}