145 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			145 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* function implementations */
 | |
| void
 | |
| clearcmd(const Arg *arg)
 | |
| {
 | |
| 	unsigned int i;
 | |
| 
 | |
| 	for (i = 0; i < LENGTH(cmdkeysym); i++) {
 | |
| 		cmdkeysym[i] = 0;
 | |
| 		cmdmod[i] = 0;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void
 | |
| grabkeys(void)
 | |
| {
 | |
| 	if (keymode == INSERTMODE) {
 | |
| 		grabdefkeys();
 | |
| 	} else if (keymode == COMMANDMODE) {
 | |
| 		XUngrabKey(dpy, AnyKey, AnyModifier, root);
 | |
| 		XGrabKey(dpy, AnyKey, AnyModifier, root,
 | |
| 			 True, GrabModeAsync, GrabModeAsync);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| int
 | |
| isprotodel(Client *c)
 | |
| {
 | |
| 	int n;
 | |
| 	Atom *protocols;
 | |
| 	int ret = 0;
 | |
| 
 | |
| 	if (XGetWMProtocols(dpy, c->win, &protocols, &n)) {
 | |
| 		while (!ret && n--)
 | |
| 			ret = protocols[n] == wmatom[WMDelete];
 | |
| 		XFree(protocols);
 | |
| 	}
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| void
 | |
| keypress(XEvent *e)
 | |
| {
 | |
| 	unsigned int i, j;
 | |
| 	Arg a = {0};
 | |
| 	Bool ismatch = False, maybematch = False;
 | |
| 	KeySym keysym;
 | |
| 	XKeyEvent *ev;
 | |
| 
 | |
| 	if (keymode == INSERTMODE)
 | |
| 		keydefpress(e);
 | |
| 	else if (keymode == COMMANDMODE) {
 | |
| 		ev = &e->xkey;
 | |
| 		keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
 | |
| 		if (keysym < XK_Shift_L || keysym > XK_Hyper_R) {
 | |
| 			for (i = 0; i < LENGTH(cmdkeys); i++)
 | |
| 				if (keysym == cmdkeys[i].keysym
 | |
| 				&& CLEANMASK(cmdkeys[i].mod) == CLEANMASK(ev->state)
 | |
| 				&& cmdkeys[i].func) {
 | |
| 					cmdkeys[i].func(&(cmdkeys[i].arg));
 | |
| 					ismatch = True;
 | |
| 					break;
 | |
| 				}
 | |
| 			if (!ismatch) {
 | |
| 				for (j = 0; j < LENGTH(cmdkeysym); j++)
 | |
| 					if (cmdkeysym[j] == 0) {
 | |
| 						cmdkeysym[j] = keysym;
 | |
| 						cmdmod[j] = ev->state;
 | |
| 						break;
 | |
| 					}
 | |
| 				for (i = 0; i < LENGTH(commands); i++) {
 | |
| 					for (j = 0; j < LENGTH(cmdkeysym); j++) {
 | |
| 						if (cmdkeysym[j] == commands[i].keysym[j]
 | |
| 						&& CLEANMASK(cmdmod[j]) == CLEANMASK(commands[i].mod[j]))
 | |
| 							ismatch = True;
 | |
| 						else if (cmdkeysym[j] == 0
 | |
| 						&& cmdmod[j] == 0) {
 | |
| 							ismatch = False;
 | |
| 							maybematch = True;
 | |
| 							break;
 | |
| 						} else {
 | |
| 							ismatch = False;
 | |
| 							break;
 | |
| 						}
 | |
| 					}
 | |
| 					if (ismatch) {
 | |
| 						if (commands[i].func)
 | |
| 							commands[i].func(&(commands[i].arg));
 | |
| 						clearcmd(&a);
 | |
| 						break;
 | |
| 					}
 | |
| 
 | |
| 				}
 | |
| 				if (!maybematch)
 | |
| 					clearcmd(&a);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void
 | |
| onlyclient(const Arg *arg)
 | |
| {
 | |
| 	Client *c;
 | |
| 	XEvent ev;
 | |
| 
 | |
| 	if (!selmon->sel)
 | |
| 		return;
 | |
| 	for (c = selmon->clients; c; c = c->next) {
 | |
| 		if (c != selmon->sel && ISVISIBLE(c)) {
 | |
| 			if (isprotodel(c)) {
 | |
| 				ev.type = ClientMessage;
 | |
| 				ev.xclient.window = c->win;
 | |
| 				ev.xclient.message_type = wmatom[WMProtocols];
 | |
| 				ev.xclient.format = 32;
 | |
| 				ev.xclient.data.l[0] = wmatom[WMDelete];
 | |
| 				ev.xclient.data.l[1] = CurrentTime;
 | |
| 				XSendEvent(dpy, c->win, False, NoEventMask, &ev);
 | |
| 			}
 | |
| 			else {
 | |
| 				XGrabServer(dpy);
 | |
| 				XSetErrorHandler(xerrordummy);
 | |
| 				XSetCloseDownMode(dpy, DestroyAll);
 | |
| 				XKillClient(dpy, c->win);
 | |
| 				XSync(dpy, False);
 | |
| 				XSetErrorHandler(xerror);
 | |
| 				XUngrabServer(dpy);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void
 | |
| setkeymode(const Arg *arg)
 | |
| {
 | |
| 	Arg a = {0};
 | |
| 
 | |
| 	if (!arg)
 | |
| 		return;
 | |
| 	keymode = arg->ui;
 | |
| 	clearcmd(&a);
 | |
| 	grabkeys();
 | |
| }
 | |
| 
 |