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