1 #include "config.h"
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <assert.h>
6 #include <sys/types.h>
7 #include <sys/time.h>
8 #include <X11/Xproto.h>
9 #include <X11/Xatom.h>
10 #include <X11/Xlib.h>
11 #include <X11/Xutil.h>
12 #include <X11/Xresource.h>
13 #include <X11/keysym.h>
14
15 #include "WinMgr.h"
16
17 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
18 #define KEY_MODMASK(x) ((x) & (ControlMask | ShiftMask | Mod1Mask))
19
20 static char *displayName = 0;
21 static Display *display = 0;
22 static Colormap defaultColormap;
23 static Window root = None;
24 static Window window = None;
25 ///static GC gc;
26
27 static long workspaceCount = 4;
28 static long activeWorkspace = 0;
29 static long windowWorkspace = 0;
30 static long state[2] = { 0, 0 };
31 ///static bool sticky = false;
32
33 static Atom _XA_WIN_WORKSPACE;
34 static Atom _XA_WIN_WORKSPACE_NAMES;
35 static Atom _XA_WIN_STATE;
36 static Atom _XA_WIN_LAYER;
37 static Atom _XA_WIN_WORKAREA;
38 static Atom _XA_WIN_TRAY;
39 static Atom _XA_NET_WM_MOVERESIZE;
40
changeWorkspace(Window w,long workspace)41 void changeWorkspace(Window w, long workspace) {
42 XClientMessageEvent xev;
43
44 memset(&xev, 0, sizeof(xev));
45 xev.type = ClientMessage;
46 xev.window = w;
47 xev.message_type = _XA_WIN_WORKSPACE;
48 xev.format = 32;
49 xev.data.l[0] = workspace;
50 xev.data.l[1] = CurrentTime; //xev.data.l[1] = timeStamp;
51 XSendEvent(display, root, False, SubstructureNotifyMask, (XEvent *) &xev);
52 }
53
moveResize(Window w,int x,int y,int what)54 void moveResize(Window w, int x, int y, int what) {
55 XClientMessageEvent xev;
56
57 memset(&xev, 0, sizeof(xev));
58 xev.type = ClientMessage;
59 xev.window = w;
60 xev.message_type = _XA_NET_WM_MOVERESIZE;
61 xev.format = 32;
62 xev.data.l[0] = x;
63 xev.data.l[1] = y; //xev.data.l[1] = timeStamp;
64 xev.data.l[2] = what;
65 XSendEvent(display, root, False, SubstructureNotifyMask, (XEvent *) &xev);
66 }
67
toggleState(Window w,long new_state)68 void toggleState(Window w, long new_state) {
69 XClientMessageEvent xev;
70
71 memset(&xev, 0, sizeof(xev));
72 xev.type = ClientMessage;
73 xev.window = w;
74 xev.message_type = _XA_WIN_STATE;
75 xev.data.l[0] = (state[0] & state[1] & new_state) ^ new_state;
76 xev.data.l[1] = new_state;
77 xev.data.l[2] = CurrentTime; //xev.data.l[1] = timeStamp;
78
79 XSendEvent(display, root, False, SubstructureNotifyMask, (XEvent *) &xev);
80 }
81
setLayer(Window w,long layer)82 void setLayer(Window w, long layer) {
83 XClientMessageEvent xev;
84
85 memset(&xev, 0, sizeof(xev));
86 xev.type = ClientMessage;
87 xev.window = w;
88 xev.message_type = _XA_WIN_LAYER;
89 xev.format = 32;
90 xev.data.l[0] = layer;
91 xev.data.l[1] = CurrentTime; //xev.data.l[1] = timeStamp;
92 XSendEvent(display, root, False, SubstructureNotifyMask, (XEvent *) &xev);
93 }
94
setTrayHint(Window w,long tray_opt)95 void setTrayHint(Window w, long tray_opt) {
96 XClientMessageEvent xev;
97
98 memset(&xev, 0, sizeof(xev));
99 xev.type = ClientMessage;
100 xev.window = w;
101 xev.message_type = _XA_WIN_TRAY;
102 xev.format = 32;
103 xev.data.l[0] = tray_opt;
104 xev.data.l[1] = CurrentTime; //xev.data.l[1] = timeStamp;
105 XSendEvent(display, root, False, SubstructureNotifyMask, (XEvent *) &xev);
106 }
107
main()108 int main(/*int argc, char **argv*/) {
109 XSetWindowAttributes attr;
110
111 assert((display = XOpenDisplay(displayName)) != 0);
112 root = RootWindow(display, DefaultScreen(display));
113 defaultColormap = DefaultColormap(display, DefaultScreen(display));
114
115 _XA_WIN_WORKSPACE = XInternAtom(display, XA_WIN_WORKSPACE, False);
116 _XA_WIN_WORKSPACE_NAMES = XInternAtom(display, XA_WIN_WORKSPACE_NAMES, False);
117 _XA_WIN_STATE = XInternAtom(display, XA_WIN_STATE, False);
118 _XA_WIN_LAYER = XInternAtom(display, XA_WIN_LAYER, False);
119 _XA_WIN_WORKAREA = XInternAtom(display, XA_WIN_WORKAREA, False);
120 _XA_WIN_TRAY = XInternAtom(display, XA_WIN_TRAY, False);
121 _XA_NET_WM_MOVERESIZE = XInternAtom(display, "_NET_WM_MOVERESIZE", False);
122
123 window = XCreateWindow(display, root,
124 0,
125 0,
126 64, 64,
127 0,
128 CopyFromParent, InputOutput, CopyFromParent,
129 0, &attr);
130
131 XSetWindowBackground(display, window, BlackPixel(display, DefaultScreen(display)));
132
133 XSelectInput(display, window,
134 ExposureMask | StructureNotifyMask |
135 ButtonPressMask | ButtonReleaseMask |
136 KeyPressMask | KeyReleaseMask |
137 PropertyChangeMask);
138
139 XSelectInput(display, root, PropertyChangeMask);
140
141 XMapRaised(display, window);
142
143 while (1) {
144 XEvent xev;
145 /// XButtonEvent &button = xev.xbutton;
146 XPropertyEvent &property = xev.xproperty;
147 XKeyEvent &key = xev.xkey;
148
149 XNextEvent(display, &xev);
150
151 switch (xev.type) {
152 case KeyPress:
153 {
154 unsigned int k = XKeycodeToKeysym(display, key.keycode, 0);
155 unsigned int m = KEY_MODMASK(key.state);
156
157 if (k == XK_Left && m == 0)
158 changeWorkspace(root,
159 (workspaceCount +
160 activeWorkspace - 1) % workspaceCount);
161 else if (k == XK_Right && m == 0)
162 changeWorkspace(root,
163 (activeWorkspace + 1) % workspaceCount);
164 else if (k == XK_Left && m == ShiftMask)
165 changeWorkspace(window,
166 (workspaceCount +
167 windowWorkspace - 1) % workspaceCount);
168 else if (k == XK_Right && m == ShiftMask)
169 changeWorkspace(window,
170 (windowWorkspace + 1) % workspaceCount);
171 else if (k == 's')
172 toggleState(window, WinStateSticky);
173 /*
174 else if (k == 'd')
175 toggleState(window, WinStateDockHorizontal);
176 */
177 else if (k == '0')
178 setLayer(window, WinLayerDesktop);
179 else if (k == '1')
180 setLayer(window, WinLayerBelow);
181 else if (k == '2')
182 setLayer(window, WinLayerNormal);
183 else if (k == '3')
184 setLayer(window, WinLayerOnTop);
185 else if (k == '4')
186 setLayer(window, WinLayerDock);
187 else if (k == '5')
188 setLayer(window, WinLayerAboveDock);
189 else if (k == 'm') {
190 printf("%d %d\n", key.x_root, key.y_root);
191 moveResize(window, key.x_root, key.y_root, 8); // move
192 } else if (k == 'r') {
193 printf("%d %d\n", key.x_root, key.y_root);
194 moveResize(window, key.x_root, key.y_root, 4); // _|
195 }
196 }
197 break;
198 case PropertyNotify:
199 {
200 Atom r_type;
201 int r_format;
202 unsigned long count;
203 unsigned long bytes_remain;
204 unsigned char *prop(0);
205
206 if (property.window == root) {
207 if (property.atom == _XA_WIN_WORKSPACE) {
208 if (XGetWindowProperty(display, root,
209 _XA_WIN_WORKSPACE,
210 0, 1, False, XA_CARDINAL,
211 &r_type, &r_format,
212 &count, &bytes_remain, &prop) == Success && prop)
213 {
214 if (r_type == XA_CARDINAL && r_format == 32 && count == 1) {
215 activeWorkspace = ((long *)prop)[0];
216 printf("active=%ld of %ld\n", activeWorkspace, workspaceCount);
217 }
218 XFree(prop);
219 }
220 } else if (property.atom == _XA_WIN_WORKSPACE_NAMES) {
221 } else if (property.atom == _XA_WIN_WORKAREA) {
222 if (XGetWindowProperty(display, root,
223 _XA_WIN_WORKAREA,
224 0, 4, False, XA_CARDINAL,
225 &r_type, &r_format,
226 &count, &bytes_remain, &prop) == Success && prop)
227 {
228 if (r_type == XA_CARDINAL && r_format == 32 && count == 4) {
229 long *area = (long *)prop;
230 printf("workarea: min=%ld,%ld max=%ld,%ld\n",
231 area[0],
232 area[1],
233 area[2],
234 area[3]);
235 }
236 XFree(prop);
237 }
238 }
239 } else if (property.window == window) {
240 if (property.atom == _XA_WIN_WORKSPACE) {
241 if (XGetWindowProperty(display, window,
242 _XA_WIN_WORKSPACE,
243 0, 1, False, XA_CARDINAL,
244 &r_type, &r_format,
245 &count, &bytes_remain, &prop) == Success && prop)
246 {
247 if (r_type == XA_CARDINAL && r_format == 32 && count == 1) {
248 windowWorkspace = ((long *)prop)[0];
249 printf("window=%ld of %ld\n", windowWorkspace, workspaceCount);
250 }
251 XFree(prop);
252 }
253 } else if (property.atom == _XA_WIN_STATE) {
254 if (XGetWindowProperty(display, window,
255 _XA_WIN_STATE,
256 0, 2, False, XA_CARDINAL,
257 &r_type, &r_format,
258 &count, &bytes_remain, &prop) == Success && prop)
259 {
260 if (r_type == XA_CARDINAL && r_format == 32 && count == 2) {
261 state[0] = ((long *)prop)[0];
262 state[1] = ((long *)prop)[1];
263 printf("state=%lX %lX\n", state[0], state[1]);
264 }
265 XFree(prop);
266 }
267 } else if (property.atom == _XA_WIN_LAYER) {
268 if (XGetWindowProperty(display, window,
269 _XA_WIN_LAYER,
270 0, 1, False, XA_CARDINAL,
271 &r_type, &r_format,
272 &count, &bytes_remain, &prop) == Success && prop)
273 {
274 if (r_type == XA_CARDINAL && r_format == 32 && count == 1) {
275 long layer = ((long *)prop)[0];
276 printf("layer=%ld\n", layer);
277 }
278 XFree(prop);
279 }
280 } else if (property.atom == _XA_WIN_TRAY) {
281 if (XGetWindowProperty(display, window,
282 _XA_WIN_TRAY,
283 0, 1, False, XA_CARDINAL,
284 &r_type, &r_format,
285 &count, &bytes_remain, &prop) == Success && prop)
286 {
287 if (r_type == XA_CARDINAL && r_format == 32 && count == 1) {
288 long tray = ((long *)prop)[0];
289 printf("tray option=%ld\n", tray);
290 }
291 }
292 }
293 }
294 }
295 }
296 }
297 }
298
299 // vim: set sw=4 ts=4 et:
300