wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

main.c (4507B)


      1 /* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
      2  * See LICENSE file for license details.
      3  */
      4 #define EXTERN
      5 #include "dat.h"
      6 #include <X11/Xproto.h>
      7 #include <locale.h>
      8 #include <stdio.h>
      9 #include <string.h>
     10 #include <stuff/clientutil.h>
     11 #include <sys/signal.h>
     12 #include "fns.h"
     13 
     14 static const char version[] = "witray-"VERSION", "COPYRIGHT"\n";
     15 
     16 static int	exitsignal;
     17 static struct sigaction	sa;
     18 
     19 static void
     20 usage(void) {
     21 	fprint(2, "usage: %s [-a <address>] [-NESW] [-HVn] [-p <padding>] [-s <iconsize>] [-t tags]\n"
     22 	          "       %s -v\n", argv0, argv0);
     23 	exit(1);
     24 }
     25 
     26 static int
     27 errfmt(Fmt *f) {
     28 	return fmtstrcpy(f, ixp_errbuf());
     29 }
     30 
     31 static void
     32 cleanup_handler(int signal) {
     33 	sa.sa_handler = SIG_DFL;
     34 	sigaction(signal, &sa, nil);
     35 
     36 	selection_release(tray.selection);
     37 	srv.running = false;
     38 
     39 	switch(signal) {
     40 	case SIGINT:
     41 	case SIGTERM:
     42 		sa.sa_handler = cleanup_handler;
     43 		sigaction(SIGALRM, &sa, nil);
     44 		alarm(1);
     45 	default:
     46 		exitsignal = signal;
     47 		break;
     48 	case SIGALRM:
     49 		raise(SIGTERM);
     50 	}
     51 }
     52 
     53 static void
     54 init_traps(void) {
     55 
     56 	sa.sa_flags = 0;
     57 	sa.sa_handler = cleanup_handler;
     58 	sigaction(SIGINT, &sa, nil);
     59 	sigaction(SIGTERM, &sa, nil);
     60 	sigaction(SIGQUIT, &sa, nil);
     61 	sigaction(SIGHUP, &sa, nil);
     62 	sigaction(SIGUSR1, &sa, nil);
     63 	sigaction(SIGUSR2, &sa, nil);
     64 }
     65 
     66 void
     67 cleanup(Selection *s) {
     68 	USED(s);
     69 
     70 	while(tray.clients)
     71 		client_disown(tray.clients);
     72 	tray.selection = nil;
     73 	srv.running = false;
     74 }
     75 
     76 void
     77 message(Selection *s, XClientMessageEvent *ev) {
     78 	Window *w;
     79 	Client *c;
     80 
     81 	USED(s);
     82 
     83 	Dprint("message(%A) 0x%lx\n", ev->message_type, ev->window);
     84 	Dprint("\t0x%lx, 0x%lx, 0x%ulx, 0x%ulx, 0x%ulx\n",
     85 	       ev->data.l[0], ev->data.l[1], ev->data.l[2], ev->data.l[3], ev->data.l[4]);
     86 
     87 	w = findwin(ev->window);
     88 	if(w == nil)
     89 		return;
     90 
     91 	if(w == tray.selection->owner) {
     92 		if(ev->message_type == NET("SYSTEM_TRAY_OPCODE") && ev->format == 32)
     93 			if(ev->data.l[1] == TrayRequestDock)
     94 				client_manage(ev->data.l[2]);
     95 		return;
     96 	}
     97 
     98 	if((c = client_find(w))) {
     99 		if(ev->message_type == NET("SYSTEM_TRAY_OPCODE") && ev->format == 32)
    100 			client_opcode(w->aux, ev->data.l[1], ev->data.l[2], ev->data.l[3], ev->data.l[4]);
    101 		else
    102 			client_message(w->aux, ev->message_type, ev->format, (ClientMessageData*)&ev->data);
    103 		return;
    104 	}
    105 }
    106 
    107 ErrorCode ignored_xerrors[] = {
    108 	{ 0, BadWindow },
    109 	{ X_GetAtomName, BadAtom },
    110 };
    111 
    112 int
    113 main(int argc, char *argv[]) {
    114 	static char* address;
    115 	bool steal;
    116 
    117 	program_args = argv;
    118 
    119 	setlocale(LC_CTYPE, "");
    120 	fmtinstall('r', errfmt);
    121 	fmtinstall('E', fmtevent);
    122 
    123 	steal = true;
    124 	tray.orientation = OHorizontal;
    125 	tray.tags = "/./";
    126 	tray.padding = 1;
    127 
    128 	ARGBEGIN{
    129 	case 'N':
    130 		tray.edge = (tray.edge & ~South) | North;
    131 		break;
    132 	case 'S':
    133 		tray.edge = (tray.edge & ~North) | South;
    134 		break;
    135 	case 'E':
    136 		tray.edge = (tray.edge & ~West) | East;
    137 		break;
    138 	case 'W':
    139 		tray.edge = (tray.edge & ~East) | West;
    140 		break;
    141 	case 'H':
    142 		tray.orientation = OHorizontal;
    143 		break;
    144 	case 'V':
    145 		tray.orientation = OVertical;
    146 		break;
    147 	case 'n':
    148 		steal = false;
    149 		break;
    150 	case 'p':
    151 		if(!getulong(EARGF(usage()), &tray.padding))
    152 			usage();
    153 		tray.padding = max(1, min(10, (int)tray.padding));
    154 		break;
    155 	case 's':
    156 		if(!getulong(EARGF(usage()), &tray.iconsize))
    157 			usage();
    158 		tray.iconsize = max(1, (int)tray.iconsize);
    159 		break;
    160 	case 't':
    161 		tray.tags = EARGF(usage());
    162 		break;
    163 	case 'a':
    164 		address = EARGF(usage());
    165 		break;
    166 	case 'D':
    167 		debug++;
    168 		break;
    169 	case 'v':
    170 		lprint(1, "%s", version);
    171 		return 0;
    172 	default:
    173 		usage();
    174 	}ARGEND;
    175 
    176 	if(argc)
    177 		usage();
    178 
    179 	init_traps();
    180 	initdisplay();
    181 
    182 	srv.preselect = event_preselect;
    183 	ixp_listen(&srv, ConnectionNumber(display), nil, event_fdready, event_fdclosed);
    184 
    185 	event_updatextime();
    186 	tray.selection = selection_manage(sxprint(Net("SYSTEM_TRAY_S%d"), scr.screen),
    187 					  event_xtime, message, cleanup, steal);
    188 	if(tray.selection == nil)
    189 		fatal("Another system tray is already running.");
    190 	if(tray.selection->oldowner)
    191 		lprint(1, "%s: Replacing currently running system tray.\n", argv0);
    192 
    193 	xext_init();
    194 	tray_init();
    195 
    196 	client_init(address);
    197 
    198 	if(tray.edge == 0)
    199 		tray.edge = West | (!strcmp(readctl("/ctl", "bar on "), "top") ? North : South);
    200 
    201 	client_readconfig(&tray.normcolors, &tray.selcolors, &tray.font);
    202 
    203 	if(tray.iconsize == 0) /* Default to wmii's bar size. */
    204 		tray.iconsize = labelh(tray.font) - 2 * tray.padding;
    205 
    206 	srv.running = true;
    207 	ixp_serverloop(&srv);
    208 
    209 	if(tray.selection)
    210 		selection_release(tray.selection);
    211 
    212 	XCloseDisplay(display);
    213 
    214 	if(exitsignal)
    215 		raise(exitsignal);
    216 	return 0;
    217 }
    218