Beispiel #1
0
void* client_thread(void* x)
#endif
{
	puts("client_thread started");
	unsigned int i;
	while(1)
	{
		mutex_lock(&client_vector_mutex);
		for(i = 0; i < clients.size; i++)
		{
			struct client* client = VECTOR_GET_AS(clients, i, struct client);
			if(client_update(client) < 0)
			{
				puts("client disconnected!");
				vector_erase(clients, i);
				i--;
				continue;
			}
			else
			{
				
			}
		}
		mutex_unlock(&client_vector_mutex);
	}
	#ifndef _WIN32
	return NULL;
	#endif
}
Beispiel #2
0
void cfg_reinitialize(void) {
	int i;
	#ifdef USE_XFT
	int xft = xftfont ? 1 : 0;
	#endif
	/* free things from old configuration */
	XFreeGC(dpy, gc);
	XFreeGC(dpy, igc);
	XFreeGC(dpy, bgc);
	XFreeGC(dpy, ibgc);
	keys_free();
	/* read config again */
	cfg_read(0);
	/* update some things */
	p_attr.background_pixel = fg.pixel;
	p_attr.border_pixel = ibfg.pixel;
	select_root_events();
	/* update clients */
	for(i = 0; i < cn; i++) {
		#ifdef USE_XFT
		if(xftfont && !xft)
			clients[i]->wlist_draw = XftDrawCreate(dpy, clients[i]->wlist_item, visual, colormap);
		if(!xftfont && xft) {
			XftDrawDestroy(clients[i]->title_draw);
			XftDrawDestroy(clients[i]->wlist_draw);
		}
		#endif
		XDestroyWindow(dpy, clients[i]->button_parent_left);
		XDestroyWindow(dpy, clients[i]->button_parent_right);
		free((void *) clients[i]->buttons);
		clients[i]->flags ^= clients[i]->flags & HAS_BUTTONS;
		buttons_create(clients[i]); /* buttons are now on top of the client window */
		XRaiseWindow(dpy, clients[i]->window); /* hence this line */
		client_update(clients[i]);
		client_update_name(clients[i]);
		(clients[i] == current) ? client_set_bg(clients[i], bg, fg) : client_set_bg(clients[i], ibg, ifg);
		if(clients[i]->flags & IS_TASKBAR)
			client_set_layer(clients[i], taskbar_ontop ? TOP : NORMAL);
		XUngrabButton(dpy, AnyButton, AnyModifier, clients[i]->parent);
		client_grab_buttons(clients[i]);
		if(clients[i]->flags & FULLSCREEN && clients[i]->layer <= NORMAL && fullscreen_stacking != FS_NORMAL)
			client_update_layer(clients[i], (fullscreen_stacking == FS_ALWAYS_ONTOP) ? NORMAL : TOP);
		if(clients[i]->flags & HAS_BORDER)
			XSetWindowBorderWidth(dpy, clients[i]->parent, border_width);
		ewmh_update_extents(clients[i]);
	}
	ewmh_update_number_of_desktops();
	ewmh_update_geometry();
	ewmh_update_strut();
}
Beispiel #3
0
void ewmh_update_strut(void) {
	Atom rt;
	int i, j, rf, scr;
	unsigned long nir, bar;
	long workarea[16], *data;
	unsigned char *p;
	for(i = 0; i < nscreens; i++)
		for(j = 0; j < 4; j++)
			screens[i].ewmh_strut[j] = 0;
	for(i = 0; i < cn; i++) {
		client_update_screen(clients[i]);
		if(XGetWindowProperty(dpy, clients[i]->window, ewmh_atoms[NET_WM_STRUT_PARTIAL], 0, 4, False, XA_CARDINAL, &rt, &rf, &nir, &bar, (unsigned char **) &p) != Success || nir < 4)
			if(XGetWindowProperty(dpy, clients[i]->window, ewmh_atoms[NET_WM_STRUT], 0, 4, False, XA_CARDINAL, &rt, &rf, &nir, &bar, (unsigned char **) &p) != Success || nir < 4)
				continue;
		data = (long *) p;
		if(data[0])
			screens[clients[i]->screen].ewmh_strut[0] += data[0] - (screens_leftmost() + screens[clients[i]->screen].x);
		if(data[1])
			screens[clients[i]->screen].ewmh_strut[1] += data[1] - (screens_rightmost() - (screens[clients[i]->screen].x + screens[clients[i]->screen].width));
		if(data[2])
			screens[clients[i]->screen].ewmh_strut[2] += data[2] - (screens_topmost() + screens[clients[i]->screen].y);
		if(data[3])
			screens[clients[i]->screen].ewmh_strut[3] += data[3] - (screens_bottom() - (screens[clients[i]->screen].y + screens[clients[i]->screen].height));
		XFree((void *) p);
	}
	scr = (ewmh_screen < nscreens) ? ewmh_screen : nscreens - 1;
	workarea[0] = screens[scr].x + screens[scr].ewmh_strut[0];
	workarea[1] = screens[scr].x + screens[scr].ewmh_strut[2];
	workarea[2] = (screens[scr].width - screens[scr].x) - (screens[scr].ewmh_strut[0] + screens[scr].ewmh_strut[1]);
	workarea[3] = (screens[scr].height - screens[scr].y) - (screens[scr].ewmh_strut[2] + screens[scr].ewmh_strut[3]);
	workarea[4] = workarea[0]; /* why 4 times? ask gnome developpers, this is the only way nautilus will listen to it */
	workarea[5] = workarea[1];
	workarea[6] = workarea[2];
	workarea[7] = workarea[3];
	workarea[8] = workarea[0];
	workarea[9] = workarea[1];
	workarea[10] = workarea[2];
	workarea[11] = workarea[3];
	workarea[12] = workarea[0];
	workarea[13] = workarea[1];
	workarea[14] = workarea[2];
	workarea[15] = workarea[3];
	XChangeProperty(dpy, root, ewmh_atoms[NET_WORKAREA], XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &workarea, sizeof(workarea) / sizeof(long));
	for(i = 0; i < cn; i++)
		client_update(clients[i]);
}
Beispiel #4
0
void numbers(void){
	int now = glutGet(GLUT_ELAPSED_TIME);
    int elapsedMilliseconds = now - lastFrameTime;
    float elapsedTime = elapsedMilliseconds / 1000.0f;
    lastFrameTime = now;
	float h = elapsedTime;
	
	client_update(tclient, h);

	while (enet_host_service (enet_client, & event, 10) > 0 && client_connection(tclient))
	{
	    switch (event.type)
	    {
	    	case ENET_EVENT_TYPE_RECEIVE:
				client_process_packets(tclient, &event);
	    		break;
    
	    	case ENET_EVENT_TYPE_DISCONNECT:
				client_disconnect(tclient);
				break;
	    }
	}
}
Beispiel #5
0
int
client_dispatch(struct ntp_peer *p, u_int8_t settime)
{
    struct ntp_msg		 msg;
    struct msghdr		 somsg;
    struct iovec		 iov[1];
    struct timeval		 tv;
    char			 buf[NTP_MSGSIZE];
    union {
        struct cmsghdr	hdr;
        char		buf[CMSG_SPACE(sizeof(tv))];
    } cmsgbuf;
    struct cmsghdr		*cmsg;
    ssize_t			 size;
    double			 T1, T2, T3, T4;
    time_t			 interval;

    bzero(&somsg, sizeof(somsg));
    iov[0].iov_base = buf;
    iov[0].iov_len = sizeof(buf);
    somsg.msg_iov = iov;
    somsg.msg_iovlen = 1;
    somsg.msg_control = cmsgbuf.buf;
    somsg.msg_controllen = sizeof(cmsgbuf.buf);

    T4 = getoffset();
    if ((size = recvmsg(p->query->fd, &somsg, 0)) == -1) {
        if (errno == EHOSTUNREACH || errno == EHOSTDOWN ||
                errno == ENETUNREACH || errno == ENETDOWN ||
                errno == ECONNREFUSED || errno == EADDRNOTAVAIL ||
                errno == ENOPROTOOPT || errno == ENOENT) {
            client_log_error(p, "recvmsg", errno);
            set_next(p, error_interval());
            return (0);
        } else
            fatal("recvfrom");
    }

    if (somsg.msg_flags & MSG_TRUNC) {
        client_log_error(p, "recvmsg packet", EMSGSIZE);
        set_next(p, error_interval());
        return (0);
    }

    if (somsg.msg_flags & MSG_CTRUNC) {
        client_log_error(p, "recvmsg control data", E2BIG);
        set_next(p, error_interval());
        return (0);
    }

#ifdef HAVE_RTABLE
    if (p->rtable != -1 &&
            setsockopt(p->query->fd, SOL_SOCKET, SO_RTABLE, &p->rtable,
                       sizeof(p->rtable)) == -1)
        fatal("client_dispatch setsockopt SO_RTABLE");
#endif

    for (cmsg = CMSG_FIRSTHDR(&somsg); cmsg != NULL;
            cmsg = CMSG_NXTHDR(&somsg, cmsg)) {
        if (cmsg->cmsg_level == SOL_SOCKET &&
                cmsg->cmsg_type == SCM_TIMESTAMP) {
            memcpy(&tv, CMSG_DATA(cmsg), sizeof(tv));
            T4 += tv.tv_sec + JAN_1970 + 1.0e-6 * tv.tv_usec;
            break;
        }
    }

    if (T4 < JAN_1970) {
        client_log_error(p, "recvmsg control format", EBADF);
        set_next(p, error_interval());
        return (0);
    }

    ntp_getmsg((struct sockaddr *)&p->addr->ss, buf, size, &msg);

    if (msg.orgtime.int_partl != p->query->msg.xmttime.int_partl ||
            msg.orgtime.fractionl != p->query->msg.xmttime.fractionl)
        return (0);

    if ((msg.status & LI_ALARM) == LI_ALARM || msg.stratum == 0 ||
            msg.stratum > NTP_MAXSTRATUM) {
        char s[16];

        if ((msg.status & LI_ALARM) == LI_ALARM) {
            strlcpy(s, "alarm", sizeof(s));
        } else if (msg.stratum == 0) {
            /* Kiss-o'-Death (KoD) packet */
            strlcpy(s, "KoD", sizeof(s));
        } else if (msg.stratum > NTP_MAXSTRATUM) {
            snprintf(s, sizeof(s), "stratum %d", msg.stratum);
        }
        interval = error_interval();
        set_next(p, interval);
        log_info("reply from %s: not synced (%s), next query %llds",
                 log_sockaddr((struct sockaddr *)&p->addr->ss), s,
                 (long long)interval);
        return (0);
    }

    /*
     * From RFC 2030 (with a correction to the delay math):
     *
     *     Timestamp Name          ID   When Generated
     *     ------------------------------------------------------------
     *     Originate Timestamp     T1   time request sent by client
     *     Receive Timestamp       T2   time request received by server
     *     Transmit Timestamp      T3   time reply sent by server
     *     Destination Timestamp   T4   time reply received by client
     *
     *  The roundtrip delay d and local clock offset t are defined as
     *
     *    d = (T4 - T1) - (T3 - T2)     t = ((T2 - T1) + (T3 - T4)) / 2.
     */

    T1 = p->query->xmttime;
    T2 = lfp_to_d(msg.rectime);
    T3 = lfp_to_d(msg.xmttime);

    /*
     * XXX workaround: time_t / tv_sec must never wrap.
     * around 2020 we will need a solution (64bit time_t / tv_sec).
     * consider every answer with a timestamp beyond january 2030 bogus.
     */
    if (T2 > JAN_2030 || T3 > JAN_2030) {
        set_next(p, error_interval());
        return (0);
    }

    p->reply[p->shift].offset = ((T2 - T1) + (T3 - T4)) / 2;
    p->reply[p->shift].delay = (T4 - T1) - (T3 - T2);
    p->reply[p->shift].status.stratum = msg.stratum;
    if (p->reply[p->shift].delay < 0) {
        interval = error_interval();
        set_next(p, interval);
        log_info("reply from %s: negative delay %fs, "
                 "next query %llds",
                 log_sockaddr((struct sockaddr *)&p->addr->ss),
                 p->reply[p->shift].delay, (long long)interval);
        return (0);
    }
    p->reply[p->shift].error = (T2 - T1) - (T3 - T4);
    p->reply[p->shift].rcvd = getmonotime();
    p->reply[p->shift].good = 1;

    p->reply[p->shift].status.leap = (msg.status & LIMASK);
    p->reply[p->shift].status.precision = msg.precision;
    p->reply[p->shift].status.rootdelay = sfp_to_d(msg.rootdelay);
    p->reply[p->shift].status.rootdispersion = sfp_to_d(msg.dispersion);
    p->reply[p->shift].status.refid = msg.refid;
    p->reply[p->shift].status.reftime = lfp_to_d(msg.reftime);
    p->reply[p->shift].status.poll = msg.ppoll;

    if (p->addr->ss.ss_family == AF_INET) {
        p->reply[p->shift].status.send_refid =
            ((struct sockaddr_in *)&p->addr->ss)->sin_addr.s_addr;
    } else if (p->addr->ss.ss_family == AF_INET6) {
        MD5_CTX		context;
        u_int8_t	digest[MD5_DIGEST_LENGTH];

        MD5_Init(&context);
        MD5_Update(&context, ((struct sockaddr_in6 *)&p->addr->ss)->
                   sin6_addr.s6_addr, sizeof(struct in6_addr));
        MD5_Final(digest, &context);
        memcpy((char *)&p->reply[p->shift].status.send_refid, digest,
               sizeof(u_int32_t));
    } else
        p->reply[p->shift].status.send_refid = msg.xmttime.fractionl;

    if (p->trustlevel < TRUSTLEVEL_PATHETIC)
        interval = scale_interval(INTERVAL_QUERY_PATHETIC);
    else if (p->trustlevel < TRUSTLEVEL_AGGRESSIVE)
        interval = scale_interval(INTERVAL_QUERY_AGGRESSIVE);
    else
        interval = scale_interval(INTERVAL_QUERY_NORMAL);

    set_next(p, interval);
    p->state = STATE_REPLY_RECEIVED;

    /* every received reply which we do not discard increases trust */
    if (p->trustlevel < TRUSTLEVEL_MAX) {
        if (p->trustlevel < TRUSTLEVEL_BADPEER &&
                p->trustlevel + 1 >= TRUSTLEVEL_BADPEER)
            log_info("peer %s now valid",
                     log_sockaddr((struct sockaddr *)&p->addr->ss));
        p->trustlevel++;
    }

    log_debug("reply from %s: offset %f delay %f, "
              "next query %llds %s",
              log_sockaddr((struct sockaddr *)&p->addr->ss),
              p->reply[p->shift].offset, p->reply[p->shift].delay,
              (long long)interval, print_rtable(p->rtable));

    client_update(p);
    if (settime)
        priv_settime(p->reply[p->shift].offset);

    if (++p->shift >= OFFSET_ARRAY_SIZE)
        p->shift = 0;

    return (0);
}
void MdlUpdate(int_T tid)
{
  client_update(tid);
}
Beispiel #7
0
void handle_event(XEvent *ev) {
	client *c = owner(ev->xany.window);
	#ifdef DEBUG_EVENTS
	if(ev->type != Expose && ev->type != MotionNotify && !(ev->type == ConfigureNotify && ev->xconfigure.window != root)) /* this makes the output slightly more manageable */
		printf(NAME ": handle_event(): got %s\n\twindow: 0x%X (%s)\n", event_name(ev), (unsigned int) ev->xany.window, c ? c->name : ((ev->xany.window == root) ? "root" : "unknown"));
	#endif
	if((evh && evh(ev)) || button_handle_event(ev) || ewmh_handle_event(ev) || screens_handle_event(ev)) {
		#ifdef DEBUG_EVENTS
		if(ev->type != Expose && ev->type != MotionNotify && (ev->type != ConfigureNotify && ev->xconfigure.window != root))
			printf(NAME ": handle_event(): external event handler claimed last event\n");
		#endif
		return;
	}
	if(c) {
		if(!has_child(c->parent, c->window) && ev->type != DestroyNotify && ev->type != UnmapNotify)
			return;
		switch(ev->type) {
			case UnmapNotify:
				if(c->window == ev->xunmap.window) {
					#ifdef DEBUG_EVENTS
					printf(NAME ": handle_event(): handling UnmapNotify event\n\twindow: 0x%X (%s)\n", (unsigned int) c->window, c->name);
					#endif
					if(has_child(c->parent, c->window)) {
						client_deparent(c);
						set_wm_state(c->window, WithdrawnState);
					}
					client_remove(c);
					ewmh_update_clist();
				}
				return;
			case PropertyNotify:
				if(ev->xproperty.atom == XA_WM_NAME) {
					#ifdef DEBUG_EVENTS
					printf(NAME ": handle_event(): handling PropertyNotify event\n\twindow: 0x%X (%s)\n\tproperty: XA_WM_NAME\n", (unsigned int) c->window, c->name);
					#endif
					if(c->name != no_title)
						XFree(c->name);
					#ifdef USE_XFT
					if(xftfont)
						XftDrawDestroy(c->title_draw);
					#endif
					XFreePixmap(dpy, c->title_pixmap);
					XFetchName(dpy, c->window, &c->name);
					client_update_name(c);
					XClearWindow(dpy, c->title);
					if(evh == wlist_handle_event) {
						XClearWindow(dpy, c->wlist_item);
						wlist_item_draw(c);
					}
				}
				if(ev->xproperty.atom == XA_WM_NORMAL_HINTS) {
					#ifdef DEBUG_EVENTS
					printf(NAME ": handle_event(): handling PropertyNotify event\n\twindow: 0x%X (%s)\n\tproperty: XA_WM_NORMAL_HINTS\n", (unsigned int) c->window, c->name);
					#endif
					get_normal_hints(c);
				}
				return;
			case ClientMessage:
				if(ev->xclient.message_type == xa_wm_change_state && ev->xclient.data.l[0] == IconicState) {
					#ifdef DEBUG_EVENTS
					printf(NAME ": handling ClientMessage event\n\twindow: 0x%X (%s)\n", (unsigned int) c->window, c->name);
					#endif
					client_iconify(c);
					return;
				}
				break; /* we might later need this event */
			case EnterNotify:
				if(c != current && !(c->flags & CLICK_FOCUS) && !click_focus && ev->xcrossing.mode != NotifyGrab && ev->xcrossing.mode != NotifyUngrab && ev->xcrossing.detail != NotifyInferior && (ev->xcrossing.window == c->parent || ev->xcrossing.window == c->wlist_item) && ev->xcrossing.send_event == False) {
					#ifdef DEBUG_EVENTS
					printf(NAME ": handle_event(): handling EnterNotify event\n\twindow: 0x%X (%s)\n", (unsigned int) c->window, c->name);
					#endif
					client_focus(c, true);
				}
				return;
			case Expose:
				if(ev->xexpose.count == 0 && evh == wlist_handle_event && c && ev->xexpose.window == c->wlist_item)
					wlist_item_draw(c);
				return;
			case ButtonPress:
				#ifdef DEBUG_EVENTS
				printf(NAME ": handle_event(): handling ButtonPress event\n\twindow: 0x%X (%s)\n", (unsigned int) c->window, c->name);
				#endif
				if(c != current)
					client_focus(c, true);
				XAllowEvents(dpy, ReplayPointer, CurrentTime);
				if(ev->xbutton.window != c->window) {
					if(lastclick + doubleclick_time > ev->xbutton.time && lastbutton == ev->xbutton.button && lastclick_client == c) {
						client_action(c, buttonaction(ev->xbutton.button, true), ev);
						lastclick = 0;
						lastclick_client = NULL;
						lastbutton = None;
						return;
					}
					lastclick = ev->xbutton.time;
					lastclick_client = c;
					lastbutton = ev->xbutton.button;
					client_action(c, buttonaction(ev->xbutton.button, false), ev);
				} else if(click_raise)
					client_raise(c);
				return;
			case FocusIn: /* we ignore pointer events, these happen if the input focus is on the root window */
				if(allow_focus_stealing && c != current && ev->xfocus.mode != NotifyGrab && ev->xfocus.mode != NotifyUngrab && ev->xfocus.detail != NotifyPointer) {
					#ifdef DEBUG_EVENTS
					printf(NAME ": handle_event(): handling FocusIn event\n\twindow: 0x%X (%s)\n", (unsigned int) c->window, c->name);
					#endif
					client_focus(c, false);
				}
				return;
			case FocusOut:
				if(c == current && ev->xfocus.mode != NotifyGrab && ev->xfocus.mode != NotifyUngrab && ev->xfocus.detail != NotifyInferior) {
					#ifdef DEBUG_EVENTS
					printf(NAME ": handle_event(): handling FocusOut event\n\twindow: 0x%X (%s)\n", (unsigned int) c->window, c->name);
					#endif
					if(allow_focus_stealing && ev->xfocus.detail != NotifyAncestor) {
						#ifdef DEBUG_EVENTS
						printf("\tfocus lost\n");
						#endif
						client_focus(NULL, false); /* we do this so windows that aren't managed can take focus */
					} else {
						#ifdef DEBUG_EVENTS
						printf("\tre-focussing this window\n");
						#endif
						take_focus(c);
					}
				}
				return;
			#ifdef USE_SHAPE
			default:
				if(ev->type == shape_event) {
					#ifdef DEBUG_EVENTS
					printf(NAME ": handle_event(): handling ShapeNotify event\n\twindow 0x%X (%s)\n", (unsigned int) c->window, c->name);
					#endif
					set_shape(c);
					return;
				}
			#endif
		}
	}
	switch(ev->type) {
		case MapRequest:
			c = owner(ev->xmaprequest.window);
			#ifdef DEBUG_EVENTS
			printf(NAME ": handle_event(): handling MapRequest event\n\twindow: 0x%X (%s)\n", (unsigned int) ev->xmaprequest.window, c ? c->name : "unknown");
			#endif
			if(c) {
				if(c->flags & ICONIC && has_child(c->parent, c->window)) {
					client_restore(c);
					if(focus_new)
						client_focus(c, true);
				}
			} else if(has_child(root, ev->xmaprequest.window))
				client_add(ev->xmaprequest.window, false);
			return;
		case DestroyNotify:
			c = owner(ev->xdestroywindow.window);
			if(c)
				if(c->window == ev->xdestroywindow.window) {
					#ifdef DEBUG_EVENTS
					printf(NAME ": handle_event(): handling DestroyNotify event\n\twindow 0x%X (%s)\n", (unsigned int) c->window, c->name);
					#endif
					client_remove(c);
				}
			return;
		case ConfigureRequest:
			c = owner(ev->xconfigurerequest.window);
			#ifdef DEBUG_EVENTS
			printf(NAME ": handle_event(): handling ConfigureRequest event\n\twindow 0x%X (%s)\n", (unsigned int) ev->xconfigurerequest.window, c ? c->name : "unknown");
			#endif
			if(correct_center)
				screens_correct_center(&ev->xconfigurerequest.x, &ev->xconfigurerequest.y, &ev->xconfigurerequest.width, &ev->xconfigurerequest.height);
			if(c) {
				if(!has_child(c->parent, c->window))
					return;
				if(ev->xconfigurerequest.value_mask & CWX)
					c->x = ev->xconfigurerequest.x - gxo(c, false);
				if(ev->xconfigurerequest.value_mask & CWY)
					c->y = ev->xconfigurerequest.y - gyo(c, false);
				if(ev->xconfigurerequest.value_mask & CWWidth)
					c->width = ev->xconfigurerequest.width;
				if(ev->xconfigurerequest.value_mask & CWHeight)
					c->height = ev->xconfigurerequest.height;
				client_update(c);
				#ifdef DEBUG
				printf(NAME ": handle_event(): reconfigured client 0x%X (%s) to %ix%i+%i+%i\n", (unsigned int) c->window, c->name, c->width, c->height, c->x, c->y);
				#endif
			} else if(has_child(root, ev->xconfigurerequest.window)) {
				XWindowChanges wc;
				wc.sibling = ev->xconfigurerequest.above;
				wc.stack_mode = ev->xconfigurerequest.detail;
				wc.x = ev->xconfigurerequest.x;
				wc.y = ev->xconfigurerequest.y;
				wc.width = ev->xconfigurerequest.width;
				wc.height = ev->xconfigurerequest.height;
				XConfigureWindow(dpy, ev->xconfigurerequest.window, ev->xconfigurerequest.value_mask, &wc);
			}
			return;
		case MapNotify:
			if(correct_center_unmanaged && ev->xany.window == root && !owner(ev->xmap.window)) {
				#ifdef DEBUG_EVENTS
				printf(NAME ": handle_event(): handling MapNotify event\n\twindow 0x%X (unknown)\n", (unsigned int) ev->xmap.window);
				#endif
				window_correct_center(ev->xmap.window);
			}
			return;
		case MappingNotify:
			if(ev->xmapping.request != MappingPointer) {
				#ifdef DEBUG_EVENTS
				printf(NAME ": handle_event(): handling MappingNotify event\n");
				#endif
				keys_ungrab();
				XRefreshKeyboardMapping(&ev->xmapping);
				keys_update();
			}
			return;
		case KeyPress:
			#ifdef DEBUG_EVENTS
			printf(NAME ": handle_event(): handling KeyPress event\n");
			#endif
			client_action(current, keyaction(ev), ev);
			return;
		case ButtonPress:
			if(ev->xbutton.window != root)
				return;
			#ifdef DEBUG_EVENTS
			printf(NAME ": handle_event(): handling ButtonPress event\n");
			#endif
			if(lastclick + doubleclick_time > ev->xbutton.time && lastbutton == ev->xbutton.button && lastclick_client == NULL) {
				client_action(current, root_buttonaction(ev->xbutton.button, true), ev);
				lastclick = 0;
				lastclick_client = NULL;
				lastbutton = None;
				return;
			}
			lastclick = ev->xbutton.time;
			lastclick_client = NULL;
			lastbutton = ev->xbutton.button;
			client_action(current, root_buttonaction(ev->xbutton.button, false), ev);
			return;
		case ClientMessage:
			if(ev->xclient.message_type == xa_internal_message) {
				if(((Atom) ev->xclient.data.l[0]) == xa_quit) {
					#ifdef DEBUG
					printf(NAME ": handle_event(): quit message received\n");
					#endif
					exit(0);
				}
				if(((Atom) ev->xclient.data.l[0]) == xa_reinit) {
					#ifdef DEBUG
					printf(NAME ": handle_event(): reinitialize message received\n");
					#endif
					cfg_reinitialize();
				}
			}
	}
}