Introduction
Introduction Statistics Contact Development Disclaimer Help
tmuxwm.c - tmuxwm - A window manager utilising only tmux.
git clone git://jay.scot/tmuxwm
Log
Files
Refs
README
LICENSE
---
tmuxwm.c (6524B)
---
1 /* TMUXWM.C
2 * Copyright Jesse McClure 2015
3 * License: GPLv3
4 * Compile: gcc -o tmuxwm tmuxwm.c -lX11
5 */
6
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <signal.h>
10 #include <unistd.h>
11 #include <string.h>
12 #include <X11/Xlib.h>
13 #include <X11/XKBlib.h>
14 #include <X11/keysym.h>
15 #include <X11/Xutil.h>
16 #include <X11/XF86keysym.h>
17
18 typedef struct Bind { KeySym sym; int mod; const char *const *args; } …
19 typedef const char *const Arg[];
20
21 Arg tmux_client = (Arg) {"st", "-e", "tmux", "new-session", NULL };
22
23 static Bind bind[] =
24 {
25 { XK_Return, Mod4Mask, (Arg) {"tmux", "r…
26 { XK_Tab, Mod4Mask, (Arg) {"tmux", "l…
27 { XK_space, Mod4Mask, (Arg) {"tmux", "n…
28 { XK_1, Mod4Mask, (Arg) {"tmux", …
29 { XK_2, Mod4Mask, (Arg) {"tmux", …
30 { XK_3, Mod4Mask, (Arg) {"tmux", …
31 { XK_4, Mod4Mask, (Arg) {"tmux", …
32 { XK_5, Mod4Mask, (Arg) {"tmux", …
33 { XK_6, Mod4Mask, (Arg) {"tmux", …
34 { XK_7, Mod4Mask, (Arg) {"tmux", …
35 { XK_8, Mod4Mask, (Arg) {"tmux", …
36 { XK_9, Mod4Mask, (Arg) {"tmux", …
37 { XK_h, Mod4Mask, (Arg) {"tmux", …
38 { XK_v, Mod4Mask, (Arg) {"tmux", …
39 { XK_f, Mod4Mask, (Arg) {"firefox", …
40 { XK_p, Mod4Mask, (Arg) {"rofi", …
41 { XK_z, Mod4Mask, (Arg) {"/home/jay/.bin/battery", …
42 { XK_x, Mod4Mask, (Arg) {"/home/jay/.bin/all-time", …
43 };
44
45
46 static void buttonpress(XEvent *);
47 static void configurerequest(XEvent *);
48 static void enternotify(XEvent *);
49 static void keypress(XEvent *);
50 static void maprequest(XEvent *);
51 static void unmapnotify(XEvent *);
52
53 static Display *dpy;
54 static Window root;
55 static int sw, sh;
56 static void (*handler[LASTEvent])(XEvent *) =
57 {
58 [ButtonPress] = buttonpress,
59 [ConfigureRequest] = configurerequest,
60 [EnterNotify] = enternotify,
61 [KeyPress] = keypress,
62 [MapRequest] = maprequest,
63 };
64
65 static int xerror(Display *d, XErrorEvent *e)
66 {
67 char msg[256];
68
69 XGetErrorText(d, e->error_code, msg, sizeof(msg));
70 fprintf(stderr, "[X11 %d:%d] %s\n", e->request_code, e->error_co…
71 }
72
73 static inline int spawn(Arg args)
74 {
75 if (fork() != 0)
76 return 1;
77 close(ConnectionNumber(dpy));
78 setsid();
79 execvp(args[0], args);
80 }
81
82 int main(int argc, const char **argv)
83 {
84 signal(SIGCHLD, SIG_IGN);
85 if (!(dpy = XOpenDisplay(0x0)))
86 return 1;
87 XSetErrorHandler(xerror);
88 root = DefaultRootWindow(dpy);
89 sw = DisplayWidth(dpy, DefaultScreen(dpy));
90 sh = DisplayHeight(dpy, DefaultScreen(dpy));
91 XGrabKey(dpy, XKeysymToKeycode(dpy, XK_Tab), Mod1Mask, root, Tru…
92 XGrabKey(dpy, XKeysymToKeycode(dpy, XK_Return), Mod4Mask | Shift…
93 int i;
94 for (i = 0; i < sizeof(bind) / sizeof(bind[0]); ++i)
95 XGrabKey(dpy, XKeysymToKeycode(dpy, bind[i].sym), bind[i…
96 XGrabButton(dpy, AnyButton, Mod4Mask, root, True, ButtonPressMas…
97 XSelectInput(dpy, root, SubstructureNotifyMask | SubstructureRed…
98 XEvent ev;
99 spawn(tmux_client);
100 while (!XNextEvent(dpy, &ev))
101 if (handler[ev.type])
102 handler[ev.type](&ev);
103 return 0;
104 }
105
106 void buttonpress(XEvent *ev)
107 {
108 XButtonEvent *e = &ev->xbutton;
109
110 XRaiseWindow(dpy, e->subwindow);
111 if (e->button == 2)
112 XMoveResizeWindow(dpy, e->subwindow, 0, 0, sw, sh);
113 if (e->button != 1 && e->button != 3)
114 return;
115 XGrabPointer(dpy, root, True, PointerMotionMask | ButtonReleaseM…
116 GrabModeAsync, GrabModeAsync, None, None, CurrentTi…
117 XWindowAttributes attr;
118 XGetWindowAttributes(dpy, e->subwindow, &attr);
119 int xx = e->x_root, yy = e->y_root, px, py;
120 XEvent ee;
121 while (!XMaskEvent(dpy, PointerMotionMask | ButtonReleaseMask, &…
122 if (ee.type == ButtonRelease)
123 break;
124 px = xx; py = yy; xx = ee.xbutton.x_root; yy = ee.xbutto…
125 if (e->button == 1) {
126 attr.x += xx - px; attr.y += yy - py;
127 } else if (e->button == 3) {
128 attr.width += xx - px; attr.height += yy - py;
129 if (attr.width < 12)
130 attr.width = 12;
131 else if (attr.height < 12)
132 attr.height = 12;
133 }
134 XMoveResizeWindow(dpy, e->subwindow, attr.x, attr.y, att…
135 }
136 XUngrabPointer(dpy, CurrentTime);
137 }
138
139 void configurerequest(XEvent *ev)
140 {
141 XConfigureRequestEvent *e = &ev->xconfigurerequest;
142 XWindowChanges wc;
143
144 wc.x = e->x; wc.y = e->y; wc.width = e->width; wc.height = e->he…
145 wc.sibling = Above; wc.stack_mode = e->detail; wc.border_width =…
146 XConfigureWindow(dpy, e->window, e->value_mask, &wc);
147 }
148
149 void enternotify(XEvent *ev)
150 {
151 XSetInputFocus(dpy, ev->xcrossing.window, RevertToPointerRoot, C…
152 }
153
154 void keypress(XEvent *ev)
155 {
156 XKeyEvent *e = &ev->xkey;
157 KeySym sym = XkbKeycodeToKeysym(dpy, e->keycode, 0, 0);
158 int i;
159
160 if (e->state == Mod1Mask && sym == XK_Tab) {
161 XCirculateSubwindowsUp(dpy, root);
162 } else if (e->state == (Mod4Mask | ShiftMask) && sym == XK_Retur…
163 spawn(tmux_client);
164 } else {
165 for (i = 0; i < sizeof(bind) / sizeof(bind[0]); ++i)
166 if (bind[i].sym == sym && bind[i].mod == e->stat…
167 spawn(bind[i].args);
168 }
169 }
170
171 #define MapFocus 0x01
172 #define MapFull 0x02
173
174 void maprequest(XEvent *ev)
175 {
176 XMapRequestEvent *e = &ev->xmaprequest;
177 XWindowAttributes wa;
178
179 if (!XGetWindowAttributes(dpy, e->window, &wa) || wa.override_re…
180 return;
181 int flags = MapFocus | MapFull;
182 XWMHints *wmHint;
183 if ((wmHint = XGetWMHints(dpy, e->window))) {
184 if (wmHint->flags & InputHint && !wmHint->input)
185 flags &= ~MapFocus;
186 XFree(wmHint);
187 }
188 XClassHint csHint;
189 XGetClassHint(dpy, e->window, &csHint);
190 if (strncmp(csHint.res_name, "Float", 5) == 0)
191 flags &= ~MapFull;
192 if (strncmp(csHint.res_class, "Float", 5) == 0)
193 flags &= ~MapFull;
194 Window parent;
195 if (XGetTransientForHint(dpy, e->window, &parent))
196 flags &= ~MapFull;
197 if (flags & MapFocus)
198 XSelectInput(dpy, e->window, EnterWindowMask);
199 if (flags & MapFull)
200 XMoveResizeWindow(dpy, e->window, 0, 0, sw, sh);
201 else
202 XMoveResizeWindow(dpy, e->window, wa.x, wa.y, wa.width, …
203 XMapWindow(dpy, e->window);
204 }
You are viewing proxied material from jay.scot. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.