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 }