/* Copyright (c) 1999 Decklin Foster <fosterd@hartwick.edu>
   Copyright (c) 2000 Linus Nilsson <d96ln@efd.lth.se> */

#include "yawm.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

/* The never-ending event-loop */
void do_event_loop() {
	XEvent ev;

	/* Remember to save those KeyCodes globally later instead of
	   looking them up every time */

	/* XGrab M-tab, SM-Tab and F{1, 2, 3} so these symbols are not
	   sent to the clients aswell */
	XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("Tab")), 
		 Mod1Mask, root, True, GrabModeAsync, GrabModeAsync);
	XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("Tab")), 
		 Mod1Mask | ShiftMask, root, True, GrabModeAsync, 
		 GrabModeAsync);
	XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("F1")),
		 AnyModifier, root, True, GrabModeAsync, GrabModeAsync);
	XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("F2")), 
		 AnyModifier, root, True, GrabModeAsync, GrabModeAsync);
	XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("F3")), 
		 AnyModifier, root, True, GrabModeAsync, GrabModeAsync);
	XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("F4")), 
		 AnyModifier, root, True, GrabModeAsync, GrabModeAsync);

	/* Start the child that updates the clock in the taskbar */
	if (USE_TASKBAR) {
		taskbar_start();
	}

	/* Start the event-loop */
	while (1) {
		//printf("Waiting for next event. Ev is #%x\n", &ev);
		XNextEvent(dpy, &ev);
		//printf("Caught new event\n");
#ifdef DEBUG
		show_event(ev);
#endif
		switch (ev.type) {
		case ButtonPress:
			handle_button_event(&ev.xbutton); break;
		case ConfigureRequest:
			handle_configure_request(&ev.xconfigurerequest); break;
		case MapRequest:
			handle_map_request(&ev.xmaprequest); break;
		case UnmapNotify:
			handle_unmap_event(&ev.xunmap); break;
		case ClientMessage:
			handle_client_message(&ev.xclient); break;
		case ColormapNotify:
			handle_colormap_change(&ev.xcolormap); break;
		case PropertyNotify:
			handle_property_change(&ev.xproperty); break;
		case EnterNotify:
			handle_enter_event(&ev.xcrossing); break;
		case Expose:
			handle_expose_event(&ev.xexpose); 
			break;
		case ReparentNotify:
			handle_reparent_event(&ev.xreparent); 
			break;
		case KeyPress:
			handle_keypress_event(&ev.xkey);
			break;
#ifdef SHAPE
		default: if (shape && ev.type == shape_event)
			handle_shape_change((XShapeEvent *)&ev);
#endif
		}
	}
}

/* quit_nicely is totally way fucked up. needs to be cleaned up after
   all features are added. exit() is used in the meantime */
void quit_nicely() {
	XFreeFont(dpy, font);
	if (opt_new1) {
		free(opt_new1);
	}
	while (head_client) {
		remove_client(head_client, 1);
	}
	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
	XInstallColormap(dpy, DefaultColormap(dpy, screen));
	XCloseDisplay(dpy);
	exit(0);
}

void err(char *fmt, ...) {
	va_list argp;

	fprintf(stderr, "yawm: ");
	va_start(argp, fmt);
	vfprintf(stderr, fmt, argp);
	va_end(argp);
	fprintf(stderr, "\n");
}

int handle_xerror(Display *dpy, XErrorEvent *e) {
	Client *c = find_client(e->resourceid, 0);

	if (e->error_code == BadAccess && e->resourceid == root) {
		err("root window unavailible (maybe another wm is running?)");
		exit(1);
	}
#ifdef DEBUG
	else {
		char msg[80];
		XGetErrorText(dpy, e->error_code, msg, sizeof(msg));
		err("X error (%#x): %s", e->resourceid, msg);
	}
#endif
	if (c) remove_client(c, 0);
	return 0;
}

#ifdef DEBUG
void show_event(XEvent e) {
	char *s;
	Window w;

	switch (e.type) {
	case ButtonPress:
		s = "ButtonPress"; w = e.xbutton.window; break;
	case ButtonRelease:
		s = "ButtonRelease"; w = e.xbutton.window; break;
	case ClientMessage:
		s = "ClientMessage"; w = e.xclient.window; break;
	case ColormapNotify:
		s = "ColormapNotify"; w = e.xcolormap.window; break;
	case ConfigureNotify:
		s = "ConfigNotify"; w = e.xconfigure.window; break;
	case ConfigureRequest:
		s = "ConfigRequest"; w = e.xconfigurerequest.window; break;
	case CreateNotify:
		s = "CreateNotify"; w = e.xcreatewindow.window; break;
	case DestroyNotify:
		s = "DestroyNotify"; w = e.xdestroywindow.window; break;
	case EnterNotify:
		s = "EnterNotify"; w = e.xcrossing.window; break;
	case LeaveNotify:
		s = "LeaveNotify"; w = e.xcrossing.window; break;
	case KeyPress:
		s = "KeyPressEvent"; w = e.xkey.window; break;
	case Expose:
		s = "ExposeEvent"; w = e.xexpose.window; break;
	case MapNotify:
		s = "MapNotify"; w = e.xmap.window; break;
	case MapRequest:
		s = "MapRequest"; w = e.xmaprequest.window; break;
	case MappingNotify:
		s = "MappingNotify"; w = e.xmapping.window; break;
	case MotionNotify:
		s = "MotionNotify"; w = e.xmotion.window; break;
	case PropertyNotify:
		s = "PropertyNotify"; w = e.xproperty.window; break;
	case ReparentNotify:
		s = "ReparentNotify"; w = e.xreparent.window; break;
	case ResizeRequest:
		s = "ResizeRequest"; w = e.xresizerequest.window; break;
	case UnmapNotify:
		s = "UnmapNotify"; w = e.xunmap.window; break;
	default:
		s = "unknown event"; w = None; break;
	}

	err("recieved %s,\twindow = %#x", s, w);
}

void dump_clients() {
	Client *c;

	for (c = head_client; c; c = c->next)
		err("%s (%d, %d): %#x (%#x) @ %d,%d", c->name, wm_state(c),
		    c->ignore_unmap, c->window, c->parent, c->x, c->y);
}
#endif


syntax highlighted by Code2HTML, v. 0.9.1