File: misc.c

package info (click to toggle)
evilwm 1.1.1-1
  • links: PTS, VCS
  • area: main
  • in suites: buster, sid, stretch
  • size: 332 kB
  • ctags: 426
  • sloc: ansic: 2,997; makefile: 76; sh: 30
file content (97 lines) | stat: -rw-r--r-- 2,633 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/* evilwm - Minimalist Window Manager for X
 * Copyright (C) 1999-2015 Ciaran Anscomb <evilwm@6809.org.uk>
 * see README for license and other details. */

#include <X11/Xproto.h>
#include <stdlib.h>
#include <stdarg.h>
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#include "evilwm.h"
#include "log.h"

int need_client_tidy = 0;
int ignore_xerror = 0;

/* Now do this by fork()ing twice so we don't have to worry about SIGCHLDs */
void spawn(const char *const cmd[]) {
	ScreenInfo *current_screen = find_current_screen();
	pid_t pid;

	if (current_screen && current_screen->display)
		putenv(current_screen->display);
	if (!(pid = fork())) {
		setsid();
		switch (fork()) {
			/* execvp()'s prototype is (char *const *) suggesting that it
			 * modifies the contents of the strings.  The prototype is this
			 * way due to SUS maintaining compatability with older code.
			 * However, execvp guarantees not to modify argv, so the following
			 * cast is valid. */
			case 0: execvp(cmd[0], (char *const *)cmd);
			default: _exit(0);
		}
	}
	if (pid > 0)
		wait(NULL);
}

void handle_signal(int signo) {
	(void)signo;  /* unused */
	wm_exit = 1;
}

int handle_xerror(Display *dsply, XErrorEvent *e) {
	Client *c;
	(void)dsply;  /* unused */

	LOG_ENTER("handle_xerror(error=%d, request=%d/%d, resourceid=%lx)", e->error_code, e->request_code, e->minor_code, e->resourceid);

	if (ignore_xerror) {
		LOG_DEBUG("ignoring...\n");
		LOG_LEAVE();
		return 0;
	}
	/* If this error actually occurred while setting up the new
	 * window, best let make_new_client() know not to bother */
	if (initialising != None && e->resourceid == initialising) {
		LOG_DEBUG("error caught while initialising window=%lx\n", initialising);
		initialising = None;
		LOG_LEAVE();
		return 0;
	}
	if (e->error_code == BadAccess && e->request_code == X_ChangeWindowAttributes) {
		LOG_ERROR("root window unavailable (maybe another wm is running?)\n");
		exit(1);
	}

	c = find_client(e->resourceid);
	if (c) {
		LOG_DEBUG("flagging client for removal\n");
		c->remove = 1;
		need_client_tidy = 1;
	} else {
		LOG_DEBUG("unknown error: not handling\n");
	}
	LOG_LEAVE();
	return 0;
}

/* Remove all enter events from the queue except the last of any corresponding
 * to "except"s parent. */
void discard_enter_events(Client *except) {
	XEvent tmp, putback_ev;
	int putback = 0;
	XSync(dpy, False);
	while (XCheckMaskEvent(dpy, EnterWindowMask, &tmp)) {
		if (tmp.xcrossing.window == except->parent) {
			memcpy(&putback_ev, &tmp, sizeof(XEvent));
			putback = 1;
		}
	}
	if (putback) {
		XPutBackEvent(dpy, &putback_ev);
	}
}