1 module monitor; 2 3 import std.stdio; 4 import std.string; 5 import std.algorithm; 6 7 import deimos.X11.X; 8 9 import cboxapp; 10 import window; 11 import theme.layout; 12 import config; 13 import types; 14 import kernel; 15 import theme.manager; 16 import old; 17 import utils; 18 19 struct Monitor 20 { 21 string ltsymbol; 22 float mfact; 23 int nmaster; 24 int num; 25 int by; /* bar geometry */ 26 int mx, my, mw, mh; /* screen size */ 27 int wx, wy, ww, wh; /* window area */ 28 29 uint seltags; 30 uint sellt; 31 uint[2] tagset; 32 bool showbar; 33 bool topbar; 34 Client *clients; 35 Client *sel; 36 Client *stack; 37 Monitor *next; 38 Window barwin; 39 const(Layout)*[2] lt; 40 41 struct MonitorRange 42 { 43 Monitor* monitor; 44 45 @property empty() 46 { 47 return monitor is null; 48 } 49 50 @property auto front() 51 { 52 return monitor; 53 } 54 55 auto popFront() 56 { 57 monitor = monitor.next; 58 } 59 60 int opApply(int delegate(Monitor*) dg) 61 { 62 int result = 0; 63 while(!this.empty) 64 { 65 result = dg(this.front); 66 if(result) 67 { 68 break; 69 } 70 this.popFront; 71 } 72 return result; 73 } 74 75 int opApply(int delegate(size_t, Monitor*) dg) 76 { 77 int result = 0; 78 size_t ii = 0; 79 while(!this.empty) 80 { 81 result = dg(ii++, this.front); 82 if(result) 83 { 84 break; 85 } 86 this.popFront; 87 } 88 return result; 89 } 90 } 91 } 92 93 Monitor* recttomon(int x, int y, int w, int h) 94 { 95 auto r = selmon; 96 int a, area = 0; 97 98 foreach(m; mons.range) { 99 a = INTERSECT(x, y, w, h, m); 100 if(a > area) { 101 area = a; 102 r = m; 103 } 104 } 105 return r; 106 } 107 108 Monitor* wintomon(Window w) 109 { 110 int x, y; 111 112 if(w == rootWin && getrootptr(&x, &y)) { 113 return recttomon(x, y, 1, 1); 114 } 115 auto m = mons.range.find!(mon => mon.barwin == w).front; 116 if(m) { 117 return m; 118 } 119 120 auto c = wintoclient(w); 121 if(c) { 122 return c.mon; 123 } 124 return selmon; 125 } 126 127 Monitor* dirtomon(int dir) 128 { 129 Monitor *m = null; 130 131 if(dir > 0) { 132 m = selmon.next; 133 if(m is null) { 134 m = mons; 135 } 136 } else if(selmon == mons) { 137 m = mons.range.find!"a.next is null".front; 138 } else { 139 m = mons.range.find!(a => a.next == selmon).front; 140 } 141 return m; 142 } 143 144 Monitor* createmon() 145 { 146 Monitor* m = new Monitor(); 147 148 if(m is null) { 149 die("fatal: could not malloc() %s bytes\n", Monitor.sizeof); 150 } 151 152 m.tagset[0] = m.tagset[1] = 1; 153 m.mfact = mfact; 154 m.nmaster = nmaster; 155 m.showbar = showbar; 156 m.topbar = topbar; 157 m.lt[0] = &layouts[0]; 158 m.lt[1] = &layouts[1 % LENGTH(layouts)]; 159 m.ltsymbol = layouts[0].symbol; 160 161 return m; 162 } 163 164 void arrange(Monitor *m) 165 { 166 if(m) { 167 windowManager.showhide(m.stack); 168 } else foreach(m; mons.range) { 169 windowManager.showhide(m.stack); 170 } 171 if(m) { 172 arrangemon(m); 173 restack(m); 174 } else foreach(m; mons.range) { 175 arrangemon(m); 176 } 177 } 178 179 void arrangemon(Monitor *m) { 180 181 m.ltsymbol = m.lt[m.sellt].symbol; 182 183 if(m.lt[m.sellt].arrange) 184 m.lt[m.sellt].arrange(m); 185 } 186 187 void attach(Client *c) { 188 189 c.next = c.mon.clients; 190 c.mon.clients = c; 191 } 192 193 void attachstack(Client *c) { 194 195 c.snext = c.mon.stack; 196 c.mon.stack = c; 197 }