JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
sanitized names
[dwm.git] / key.c
1 /*
2  * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
3  * See LICENSE file for license details.
4  */
5
6 #include <fcntl.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <X11/keysym.h>
12 #include <X11/Xatom.h>
13
14 #include "dwm.h"
15
16 static void ckill(Arg *arg);
17 static void nextc(Arg *arg);
18 static void prevc(Arg *arg);
19 static void max(Arg *arg);
20 static void ttrunc(Arg *arg);
21 static void tappend(Arg *arg);
22 static void zoom(Arg *arg);
23
24 /********** CUSTOMIZE **********/
25
26 const char *term[] = { 
27         "urxvtc", "-tr", "+sb", "-bg", "black", "-fg", "white", "-fn",
28         "-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*",NULL
29 };
30 const char *browse[] = { "firefox", NULL };
31 const char *xlock[] = { "xlock", NULL };
32
33 Key key[] = {
34         /* modifier                             key                     function        arguments */
35         { Mod1Mask,                             XK_Return,      zoom,           { 0 } },
36         { Mod1Mask,                             XK_k,           prevc,          { 0 } },
37         { Mod1Mask,                             XK_j,           nextc,          { 0 } }, 
38         { Mod1Mask,                             XK_m,           max,            { 0 } }, 
39         { Mod1Mask,                             XK_0,           view,           { .i = Tscratch } }, 
40         { Mod1Mask,                             XK_1,           view,           { .i = Tdev } }, 
41         { Mod1Mask,                             XK_2,           view,           { .i = Twww } }, 
42         { Mod1Mask,                             XK_3,           view,           { .i = Twork } }, 
43         { Mod1Mask,                             XK_space,       tiling,         { 0 } }, 
44         { Mod1Mask|ShiftMask,   XK_space,       floating,       { 0 } }, 
45         { Mod1Mask|ShiftMask,   XK_0,           ttrunc,         { .i = Tscratch } }, 
46         { Mod1Mask|ShiftMask,   XK_1,           ttrunc,         { .i = Tdev } }, 
47         { Mod1Mask|ShiftMask,   XK_2,           ttrunc,         { .i = Twww } }, 
48         { Mod1Mask|ShiftMask,   XK_3,           ttrunc,         { .i = Twork } }, 
49         { Mod1Mask|ShiftMask,   XK_c,           ckill,          { 0 } }, 
50         { Mod1Mask|ShiftMask,   XK_q,           quit,           { 0 } },
51         { Mod1Mask|ShiftMask,   XK_Return,      spawn,          { .argv = term } },
52         { Mod1Mask|ShiftMask,   XK_w,           spawn,          { .argv = browse } },
53         { Mod1Mask|ShiftMask,   XK_l,           spawn,          { .argv = xlock } },
54         { ControlMask,                  XK_0,           tappend,        { .i = Tscratch } }, 
55         { ControlMask,                  XK_1,           tappend,        { .i = Tdev } }, 
56         { ControlMask,                  XK_2,           tappend,        { .i = Twww } }, 
57         { ControlMask,                  XK_3,           tappend,        { .i = Twork } }, 
58 };
59
60 /********** CUSTOMIZE **********/
61
62 void
63 grabkeys()
64 {
65         static unsigned int len = key ? sizeof(key) / sizeof(key[0]) : 0;
66         unsigned int i;
67         KeyCode code;
68
69         for(i = 0; i < len; i++) {
70                 code = XKeysymToKeycode(dpy, key[i].keysym);
71                 XUngrabKey(dpy, code, key[i].mod, root);
72                 XGrabKey(dpy, code, key[i].mod, root, True,
73                                 GrabModeAsync, GrabModeAsync);
74         }
75 }
76
77 void
78 keypress(XEvent *e)
79 {
80         XKeyEvent *ev = &e->xkey;
81         static unsigned int len = key ? sizeof(key) / sizeof(key[0]) : 0;
82         unsigned int i;
83         KeySym keysym;
84
85         keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
86         for(i = 0; i < len; i++)
87                 if((keysym == key[i].keysym) && (key[i].mod == ev->state)) {
88                         if(key[i].func)
89                                 key[i].func(&key[i].arg);
90                         return;
91                 }
92 }
93
94 static void
95 zoom(Arg *arg)
96 {
97         Client **l, *c;
98
99         if(!sel)
100                 return;
101
102         if(sel == getnext(clients) && sel->next)  {
103                 if((c = getnext(sel->next)))
104                         sel = c;
105         }
106
107         for(l = &clients; *l && *l != sel; l = &(*l)->next);
108         *l = sel->next;
109
110         sel->next = clients; /* pop */
111         clients = sel;
112         arrange(NULL);
113         focus(sel);
114 }
115
116 static void
117 max(Arg *arg)
118 {
119         if(!sel)
120                 return;
121         sel->x = sx;
122         sel->y = sy + bh;
123         sel->w = sw - 2 * sel->border;
124         sel->h = sh - 2 * sel->border - bh;
125         higher(sel);
126         resize(sel, False);
127 }
128
129 static void
130 tappend(Arg *arg)
131 {
132         if(!sel)
133                 return;
134
135         sel->tags[arg->i] = tags[arg->i];
136         arrange(NULL);
137 }
138
139 static void
140 ttrunc(Arg *arg)
141 {
142         int i;
143         if(!sel)
144                 return;
145
146         for(i = 0; i < TLast; i++)
147                 sel->tags[i] = NULL;
148         tappend(arg);
149 }
150
151 static void
152 prevc(Arg *arg)
153 {
154         Client *c;
155
156         if(!sel)
157                 return;
158
159         if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) {
160                 higher(c);
161                 focus(c);
162         }
163 }
164
165 static void
166 nextc(Arg *arg)
167 {
168         Client *c;
169    
170         if(!sel)
171                 return;
172
173         if(!(c = getnext(sel->next)))
174                 c = getnext(clients);
175         if(c) {
176                 higher(c);
177                 c->revert = sel;
178                 focus(c);
179         }
180 }
181
182 static void
183 ckill(Arg *arg)
184 {
185         if(!sel)
186                 return;
187         if(sel->proto & WM_PROTOCOL_DELWIN)
188                 sendevent(sel->win, wm_atom[WMProtocols], wm_atom[WMDelete]);
189         else
190                 XKillClient(dpy, sel->win);
191 }
192