1 module kernel;
2 
3 import std.c.locale;
4 import std.c..string;
5 import std.c.stdlib;
6 
7 import std.stdio;
8 import std..string;
9 import std.algorithm;
10 import std.conv;
11 import std.process;
12 import std.traits;
13 import helper.process;
14 
15 import core.sys.posix.signal;
16 import core.sys.posix.sys.wait;
17 import core.sys.posix.unistd;
18 import core.memory;
19 
20 import x11.X;
21 import x11.Xlib;
22 import x11.keysymdef;
23 import x11.Xutil;
24 import x11.Xatom;
25 
26 import cboxapp;
27 import types;
28 import utils;
29 import legacy;
30 import old;
31 import config;
32 import events.handler;
33 import events.keyboard;
34 import events.mouse;
35 import window;
36 import helper.x11;
37 import gui.cursor;
38 import gui.font;
39 import gui.bar;
40 import theme.layout;
41 import theme.manager;
42 import monitor;
43 
44 static Drw *drw;
45 static Fnt *fnt;
46 static Key[] keys;
47 
48 /* button definitions */
49 /* click can be ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
50 static Button[] buttons;
51 static void function(XEvent*)[LASTEvent] handler;
52 
53 
54 EventHandler eventManager;
55 KeyboardEvents keyboardEventHandler;
56 MouseEvents mouseEventHandler;
57 WindowManager windowManager;
58 
59 static Atom[WMLast] wmatom;
60 static Atom[NetLast] netatom;
61 
62 void quit(const Arg *arg)
63 {
64     AppDisplay.instance().running = false;
65 }
66 
67 class Kernel
68 {
69     this()
70     {
71         keyboardEventHandler = new KeyboardEvents();
72         keyboardEventHandler.addEvent(MODKEY|ShiftMask, XK_q, &quit);
73         keyboardEventHandler.addEvent(MODKEY, XK_p, &spawn, dmenucmd);
74 
75         mouseEventHandler = new MouseEvents();
76         eventManager = new EventHandler(keyboardEventHandler, mouseEventHandler);
77         windowManager = new WindowManager();
78 
79         wmatom = windowManager.getAllAtoms("WMLast");
80         netatom = windowManager.getAllAtoms("NetLast");
81     }
82 
83     int boot()
84     {
85         keys = keyboardEventHandler.getKeys();
86         buttons = mouseEventHandler.getButtons();
87 
88         this.checkotherwm();
89         this.setup();
90         this.scan();
91         this.run();
92         this.close();
93 
94         return 0;
95     }
96 
97     void checkotherwm()
98     {
99         xerrorxlib = XSetErrorHandler(&xerrorstart);
100         /* this causes an error if some other window manager is running */
101         XSelectInput(AppDisplay.instance().dpy, DefaultRootWindow(AppDisplay.instance().dpy), SubstructureRedirectMask);
102         XSync(AppDisplay.instance().dpy, false);
103         XSetErrorHandler(&xerror);
104         XSync(AppDisplay.instance().dpy, false);
105     }
106 
107     void setup()
108     {
109         XSetWindowAttributes wa;
110 
111         /* clean up any zombies immediately */
112         sigchld(0);
113 
114         /* init screen */
115         screen = DefaultScreen(AppDisplay.instance().dpy);
116         rootWin = RootWindow(AppDisplay.instance().dpy, screen);
117 
118         fnt = new Fnt(AppDisplay.instance().dpy, font);
119         sw = DisplayWidth(AppDisplay.instance().dpy, screen);
120         sh = DisplayHeight(AppDisplay.instance().dpy, screen);
121         bh = fnt.h + 2;
122 
123         drw = new Drw(AppDisplay.instance().dpy, screen, rootWin, sw, sh);
124         drw.setfont(fnt);
125         updategeom();
126 
127         /* init cursors */
128         cursor[CurNormal] = new Cur(drw.dpy, CursorFont.XC_left_ptr);
129         cursor[CurResize] = new Cur(drw.dpy, CursorFont.XC_sizing);
130         cursor[CurMove] = new Cur(drw.dpy, CursorFont.XC_fleur);
131 
132 
133         /* init bars */
134         updatebars();
135         updatestatus();
136 
137         /* EWMH support per view */
138         XChangeProperty(
139             AppDisplay.instance().dpy,
140             rootWin,
141             windowManager.getAtom("NetLast",NetSupported),
142             XA_ATOM, 32,
143             PropModeReplace,
144             cast(ubyte*) windowManager.getAllAtoms("NetLast"),
145             NetLast
146         );
147 
148         XDeleteProperty(
149             AppDisplay.instance().dpy,
150             rootWin,
151             windowManager.getAtom("NetLast", NetClientList)
152         );
153 
154         /* select for events */
155         wa.cursor = cursor[CurNormal].cursor;
156         wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask|PointerMotionMask
157                         |EnterWindowMask|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask;
158 
159         XChangeWindowAttributes(AppDisplay.instance().dpy, rootWin, CWEventMask|CWCursor, &wa);
160         XSelectInput(AppDisplay.instance().dpy, rootWin, wa.event_mask);
161         keyboardEventHandler.grabkeys();
162 
163         focus(null);
164     }
165 
166     void scan()
167     {
168         uint i, num;
169         Window d1, d2;
170         Window* wins = null;
171         XWindowAttributes wa;
172 
173         if(XQueryTree(AppDisplay.instance().dpy, rootWin, &d1, &d2, &wins, &num)) {
174             for(i = 0; i < num; i++) {
175                 if(!XGetWindowAttributes(AppDisplay.instance().dpy, wins[i], &wa)
176                         || wa.override_redirect || XGetTransientForHint(AppDisplay.instance().dpy, wins[i], &d1))
177                     continue;
178                 if(wa.map_state == IsViewable || this.getstate(wins[i]) == IconicState)
179                     windowManager.manage(wins[i], &wa);
180             }
181             for(i = 0; i < num; i++) { /* now the transients */
182                 if(!XGetWindowAttributes(AppDisplay.instance().dpy, wins[i], &wa))
183                     continue;
184                 if(XGetTransientForHint(AppDisplay.instance().dpy, wins[i], &d1)
185                         && (wa.map_state == IsViewable || this.getstate(wins[i]) == IconicState))
186                     windowManager.manage(wins[i], &wa);
187             }
188             if(wins)
189                 XFree(wins);
190         }
191     }
192 
193     void run()
194     {
195         extern(C) __gshared XEvent ev;
196 
197         /* main event loop */
198         XSync(AppDisplay.instance().dpy, false);
199         while(AppDisplay.instance().running && !XNextEvent(AppDisplay.instance().dpy, &ev)) {
200             eventManager.listen(&ev);
201         }
202     }
203 
204     void cleanup()
205     {
206         auto a = Arg(-1);
207         Layout foo = { "", null };
208 
209         view(&a);
210         selmon.lt[selmon.sellt] = &foo;
211         foreach(m; mons.range) {
212             while(m.stack) {
213                 unmanage(m.stack, false);
214             }
215         }
216         XUngrabKey(AppDisplay.instance().dpy, AnyKey, AnyModifier, rootWin);
217         while(mons) {
218             cleanupmon(mons);
219         }
220 
221         Cur.free(cursor[CurNormal]);
222         Cur.free(cursor[CurResize]);
223         Cur.free(cursor[CurMove]);
224         Fnt.free(AppDisplay.instance().dpy, fnt);
225         Clr.free(ThemeManager.instance().getScheme(SchemeNorm).border);
226         Clr.free(ThemeManager.instance().getScheme(SchemeNorm).bg);
227         Clr.free(ThemeManager.instance().getScheme(SchemeNorm).fg);
228         Clr.free(ThemeManager.instance().getScheme(SchemeSel).border);
229         Clr.free(ThemeManager.instance().getScheme(SchemeSel).bg);
230         Clr.free(ThemeManager.instance().getScheme(SchemeSel).fg);
231 
232 
233         Drw.free(drw);
234         XSync(AppDisplay.instance().dpy, false);
235         XSetInputFocus(AppDisplay.instance().dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
236         XDeleteProperty(AppDisplay.instance().dpy, rootWin, netatom[NetActiveWindow]);
237     }
238 
239     void close()
240     {
241         this.cleanup();
242         XCloseDisplay(AppDisplay.instance().dpy);
243     }
244 
245     /**
246     * Get window State
247     **/
248     long getstate(Window w)
249     {
250         int format;
251         long result = -1;
252         ubyte *p = null;
253         ulong n, extra;
254         Atom realVal;
255 
256         if(XGetWindowProperty(AppDisplay.instance().dpy, w, wmatom[WMState], 0L, 2L, false, wmatom[WMState],
257            &realVal, &format, &n, &extra, cast(ubyte **)&p) != XErrorCode.Success) {
258             return -1;
259         }
260 
261         if(n != 0) {
262             result = *p;
263         }
264 
265         XFree(p);
266         return result;
267     }
268 
269 }