/
baconwm.c
161 lines (136 loc) · 5 KB
/
baconwm.c
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#include <stdlib.h>
#include <xcb/xcb.h>
#include <X11/keysym.h>
#include <xcb/xcb_keysyms.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <X11/X.h>
/* Macros */
#define LENGTH(x) (unsigned int)(sizeof(x) / sizeof(*x))
/* union for keys */
typedef union { const char * const * const cmd;
int i; /* may need later, we'll see. */
} Arg;
typedef struct { int mod; xcb_keysym_t sym;
void (*func) (const Arg *);
const Arg arg;
} Key;
/* xcb globals */
static void grab_keys(void); /* key grabbing function */
static xcb_keycode_t *keysym_to_keycode(xcb_keysym_t sym);
static void grab_keycode(xcb_keycode_t *keycode, const int mod);
/* general globals */
static xcb_connection_t *disp;
static xcb_screen_t *screen;
static void spawn(const Arg *arg);
#include "config.h"
int init_baconwm () {
uint32_t values[3];
xcb_drawable_t win;
xcb_drawable_t root;
xcb_generic_event_t *ev;
xcb_get_geometry_reply_t *geom;
disp = xcb_connect(NULL, NULL);
if (xcb_connection_has_error(disp)) return 1; /*kill if error on connection */
screen = xcb_setup_roots_iterator(xcb_get_setup(disp)).data;
root = screen->root;
grab_keys();
xcb_flush(disp);
/* big fucking loop */
for (;;)
{
ev = xcb_wait_for_event(disp);
switch (ev->response_type & ~0x80) {
case XCB_BUTTON_PRESS:
{
xcb_button_press_event_t *e;
e = ( xcb_button_press_event_t *) ev;
win = e->child;
values[0] = XCB_STACK_MODE_ABOVE;
xcb_configure_window(disp, win, XCB_CONFIG_WINDOW_STACK_MODE, values);
geom = xcb_get_geometry_reply(disp, xcb_get_geometry(disp, win), NULL);
if (1 == e->detail) {
values[2] = 1;
xcb_warp_pointer(disp, XCB_NONE, win, 0, 0, 0, 0, 1, 1);
} else {
values[2] = 3;
xcb_warp_pointer(disp, XCB_NONE, win, 0, 0, 0, 0, geom->width, geom->height);
}
xcb_grab_pointer(disp, 0, root, XCB_EVENT_MASK_BUTTON_RELEASE
| XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_POINTER_MOTION_HINT,
XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, root, XCB_NONE, XCB_CURRENT_TIME);
xcb_flush(disp);
}
break;
case XCB_MOTION_NOTIFY:
{
/* None of this matters, it's the tinywm stackable shizzle. */
/* I just have it here because it's cool. We will snap all */
/* spawned windows to 0,0,w,h geometry for full-screen */
xcb_query_pointer_reply_t *pointer;
pointer = xcb_query_pointer_reply(disp, xcb_query_pointer(disp, root), 0);
if (values[2] == 1) {/* move */
geom = xcb_get_geometry_reply(disp, xcb_get_geometry(disp, win), NULL);
values[0] = (pointer->root_x + geom->width > screen->width_in_pixels)?
(screen->width_in_pixels - geom->width):pointer->root_x;
values[1] = (pointer->root_y + geom->height > screen->height_in_pixels)?
(screen->height_in_pixels - geom->height):pointer->root_y;
xcb_configure_window(disp, win, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values);
xcb_flush(disp);
} else if (values[2] == 3) { /* resize */
geom = xcb_get_geometry_reply(disp, xcb_get_geometry(disp, win), NULL);
values[0] = pointer->root_x - geom->x;
values[1] = pointer->root_y - geom->y;
xcb_configure_window(disp, win, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values);
xcb_flush(disp);
}
}
break;
case XCB_BUTTON_RELEASE:
xcb_ungrab_pointer(disp, XCB_CURRENT_TIME);
xcb_flush(disp);
break;
}
}
return 0;
}
void spawn(const Arg *arg){
/* spawns a process via command */
if (fork()) return;
setsid();
execvp((char *)arg->cmd[0], (char **)arg->cmd);
}
void grab_keys(void) {
/* TODO: determine efficient way to capture keycode/keysyms */
/* then, remove previous 'place-holder code' in main loop */
int i;
xcb_keycode_t *keycode;
xcb_ungrab_key(disp, XCB_GRAB_ANY, screen->root, XCB_MOD_MASK_ANY);
for (i=0;i<LENGTH(keys);i++) {
keysym_to_keycode(keys[i].mod);
grab_keycode(keycode, keys[i].mod);
}
}
void grab_keycode(xcb_keycode_t *keycode, const int mod) {
unsigned int x, k;
uint16_t mods[] = {0, XCB_MOD_MASK_LOCK };
for (x=0; keycode[x] != XCB_NO_SYMBOL; x++)
for (k=0; k< LENGTH(mods); k++)
xcb_grab_key(disp, 1, screen->root, mod | mods[k], keycode[x],
XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
free(keycode);
}
xcb_keycode_t *keysym_to_keycode(xcb_keysym_t sym) {
xcb_keycode_t *code;
xcb_key_symbols_t *syms = xcb_key_symbols_alloc(disp);
if(!syms)
return NULL;
code = xcb_key_symbols_get_keycode(syms, sym);
xcb_key_symbols_free(syms);
return code;
}
int main () {
init_baconwm ();
return 0;
}