1 module shell; 2 3 import compositor; 4 import output; 5 import wayland.server; 6 7 import std.stdio; 8 import std.algorithm; 9 import std.range; 10 11 class Shell : WlShell 12 { 13 Compositor comp; 14 ShellSurface[] topLevels; 15 16 this (Compositor comp) 17 { 18 super(comp.display, ver); 19 this.comp = comp; 20 } 21 22 void addTopLevel(ShellSurface ss) 23 { 24 topLevels ~= ss; 25 ss.addDestroyListener((WlResource res) { 26 topLevels = topLevels.remove!(tl => res is tl); 27 }); 28 } 29 30 void mouseButton(int x, int y, int button, WlPointer.ButtonState state) 31 { 32 foreach(tl; retro(topLevels)) 33 { 34 if (x >= tl.x && x < tl.x+tl.width && 35 y >= tl.y && y < tl.y+tl.height) 36 { 37 comp.seat.mouseButton(tl.client, button, state); 38 break; 39 } 40 } 41 } 42 43 // paint windows over background (last inserted on top) 44 // a more general algorithm should be needed for other kinds of surfaces (eg. cursors) 45 void paint(Output output) 46 { 47 immutable ow = output.width; 48 immutable oh = output.height; 49 auto ob = output.buf; 50 foreach (tl; topLevels) 51 { 52 if (!(tl.surf.outputMask & output.mask)) continue; 53 54 auto sb = tl.surf.state.buffer; 55 auto sd = cast(uint[])sb.beginAccess(); 56 scope(exit) sb.endAccess(); 57 58 if (tl.unplaced) 59 { 60 tl.x = (ow - sb.width) / 2; 61 tl.y = (oh - sb.height) / 2; 62 tl.unplaced = false; 63 } 64 65 tl.width = sb.width; 66 tl.height = sb.height; 67 68 if (tl.x > ow) break; 69 70 if (sb.format == WlShm.Format.xrgb8888) 71 { 72 // no blending 73 foreach (r; 0 .. sb.height) 74 { 75 if (r + tl.y > oh) break; 76 77 immutable srcFrom = r*sb.stride/4; 78 immutable destFrom = (r+tl.y) * ow + tl.x; 79 immutable copyWidth = min( 80 sb.width, ow - tl.x 81 ); 82 ob[destFrom .. destFrom+copyWidth] = 83 sd[srcFrom .. srcFrom+copyWidth]; 84 } 85 } 86 else 87 { 88 assert(sb.format == WlShm.Format.argb8888); 89 // inefficient blending 90 foreach (r; 0 .. sb.height) 91 { 92 if (r + tl.y > oh) break; 93 94 foreach (c; 0 .. sb.width) 95 { 96 if (c + tl.x > ow) break; 97 98 immutable size_t srcInd = r*sb.stride/4 + c; 99 immutable size_t destInd = (r+tl.y) * ow + tl.x+c; 100 101 immutable uint dest = ob[destInd]; 102 immutable uint aDest = (dest & 0xff000000) >>> 24; 103 immutable uint rDest = (dest & 0xff0000) >>> 16; 104 immutable uint gDest = (dest & 0xff00) >>> 8; 105 immutable uint bDest = (dest & 0xff); 106 107 immutable uint src = sd[srcInd]; 108 immutable uint aSrc = (src & 0xff000000) >>> 24; 109 immutable uint rSrc = (src & 0xff0000) >>> 16; 110 immutable uint gSrc = (src & 0xff00) >>> 8; 111 immutable uint bSrc = (src & 0xff); 112 113 auto aRes = aSrc + aDest*(255 - aSrc) / 255; 114 115 auto rRes = ((aSrc*rSrc) + (255-aSrc)*(aDest*rDest)/255) / aRes; 116 auto gRes = ((aSrc*gSrc) + (255-aSrc)*(aDest*gDest)/255) / aRes; 117 auto bRes = ((aSrc*bSrc) + (255-aSrc)*(aDest*bDest)/255) / aRes; 118 119 if (aRes > 0xff) aRes = 0xff; 120 if (rRes > 0xff) rRes = 0xff; 121 if (gRes > 0xff) gRes = 0xff; 122 if (bRes > 0xff) bRes = 0xff; 123 124 ob[destInd] = aRes << 24 | rRes << 16 | gRes << 8 | bRes; 125 } 126 } 127 } 128 } 129 } 130 131 // WlShell 132 133 override WlShellSurface getShellSurface(WlClient cl, Resource res, uint id, WlSurface surf) 134 { 135 return new ShellSurface(cl, id, cast(Surface)surf, res, comp); 136 } 137 } 138 139 140 class ShellSurface : WlShellSurface 141 { 142 Surface surf; 143 WlShell.Resource shRes; 144 Compositor comp; 145 bool unplaced = true; 146 int x; int y; 147 int width; int height; 148 149 this(WlClient cl, uint id, Surface surf, WlShell.Resource shRes, Compositor comp) 150 { 151 super(cl, ver, id); 152 this.surf = surf; 153 this.shRes = shRes; 154 this.comp = comp; 155 } 156 157 @property Shell shell() 158 { 159 return cast(Shell)shRes.outer; 160 } 161 162 // WlShellSurface 163 164 override protected void pong(WlClient cl, 165 uint serial) 166 {} 167 168 override protected void move(WlClient cl, 169 WlSeat.Resource seat, 170 uint serial) 171 {} 172 173 override protected void resize(WlClient cl, 174 WlSeat.Resource seat, 175 uint serial, 176 Resize edges) 177 {} 178 179 180 override protected void setToplevel(WlClient cl) 181 { 182 try { 183 surf.assignRole("shell"); 184 auto output = comp.outputs[0]; 185 surf.outputMask = surf.outputMask | output.mask; 186 shell.addTopLevel(this); 187 } 188 catch (Exception ex) 189 { 190 shRes.postError(WlShell.Error.role, ex.msg); 191 } 192 } 193 194 override protected void setTransient(WlClient cl, 195 WlSurface parent, 196 int x, 197 int y, 198 Transient flags) 199 {} 200 201 override protected void setFullscreen(WlClient cl, 202 FullscreenMethod method, 203 uint framerate, 204 WlOutput.Resource outputRes) 205 {} 206 207 override protected void setPopup(WlClient cl, 208 WlSeat.Resource seat, 209 uint serial, 210 WlSurface parent, 211 int x, 212 int y, 213 Transient flags) 214 {} 215 216 override protected void setMaximized(WlClient cl, 217 WlOutput.Resource output) 218 {} 219 220 override protected void setTitle(WlClient cl, 221 string title) 222 { 223 224 } 225 226 override protected void setClass(WlClient cl, 227 string class_) 228 {} 229 230 }