1*37da2899SCharles.Forsythimplement Wmsrv; 2*37da2899SCharles.Forsyth 3*37da2899SCharles.Forsythinclude "sys.m"; 4*37da2899SCharles.Forsyth sys: Sys; 5*37da2899SCharles.Forsythinclude "draw.m"; 6*37da2899SCharles.Forsyth draw: Draw; 7*37da2899SCharles.Forsyth Display, Image, Point, Rect, Screen, Pointer, Context, Wmcontext: import draw; 8*37da2899SCharles.Forsythinclude "wmsrv.m"; 9*37da2899SCharles.Forsyth 10*37da2899SCharles.Forsythzorder: ref Client; # top of z-order list, linked by znext. 11*37da2899SCharles.Forsyth 12*37da2899SCharles.ForsythZR: con Rect((0, 0), (0, 0)); 13*37da2899SCharles.ForsythIqueue: adt { 14*37da2899SCharles.Forsyth h, t: list of int; 15*37da2899SCharles.Forsyth n: int; 16*37da2899SCharles.Forsyth put: fn(q: self ref Iqueue, s: int); 17*37da2899SCharles.Forsyth get: fn(q: self ref Iqueue): int; 18*37da2899SCharles.Forsyth peek: fn(q: self ref Iqueue): int; 19*37da2899SCharles.Forsyth nonempty: fn(q: self ref Iqueue): int; 20*37da2899SCharles.Forsyth}; 21*37da2899SCharles.ForsythSqueue: adt { 22*37da2899SCharles.Forsyth h, t: list of string; 23*37da2899SCharles.Forsyth n: int; 24*37da2899SCharles.Forsyth put: fn(q: self ref Squeue, s: string); 25*37da2899SCharles.Forsyth get: fn(q: self ref Squeue): string; 26*37da2899SCharles.Forsyth peek: fn(q: self ref Squeue): string; 27*37da2899SCharles.Forsyth nonempty: fn(q: self ref Squeue): int; 28*37da2899SCharles.Forsyth}; 29*37da2899SCharles.Forsyth# Ptrqueue is the same as the other queues except it merges events 30*37da2899SCharles.Forsyth# that have the same button state. 31*37da2899SCharles.ForsythPtrqueue: adt { 32*37da2899SCharles.Forsyth last: ref Pointer; 33*37da2899SCharles.Forsyth h, t: list of ref Pointer; 34*37da2899SCharles.Forsyth put: fn(q: self ref Ptrqueue, s: ref Pointer); 35*37da2899SCharles.Forsyth get: fn(q: self ref Ptrqueue): ref Pointer; 36*37da2899SCharles.Forsyth peek: fn(q: self ref Ptrqueue): ref Pointer; 37*37da2899SCharles.Forsyth nonempty: fn(q: self ref Ptrqueue): int; 38*37da2899SCharles.Forsyth flush: fn(q: self ref Ptrqueue); 39*37da2899SCharles.Forsyth}; 40*37da2899SCharles.Forsyth 41*37da2899SCharles.Forsythinit(): (chan of (string, chan of (string, ref Wmcontext)), 42*37da2899SCharles.Forsyth chan of (ref Client, chan of string), 43*37da2899SCharles.Forsyth chan of (ref Client, array of byte, Sys->Rwrite)) 44*37da2899SCharles.Forsyth{ 45*37da2899SCharles.Forsyth sys = load Sys Sys->PATH; 46*37da2899SCharles.Forsyth draw = load Draw Draw->PATH; 47*37da2899SCharles.Forsyth 48*37da2899SCharles.Forsyth sys->bind("#s", "/chan", Sys->MBEFORE); 49*37da2899SCharles.Forsyth 50*37da2899SCharles.Forsyth ctlio := sys->file2chan("/chan", "wmctl"); 51*37da2899SCharles.Forsyth if(ctlio == nil){ 52*37da2899SCharles.Forsyth sys->werrstr(sys->sprint("can't create /chan/wmctl: %r")); 53*37da2899SCharles.Forsyth return (nil, nil, nil); 54*37da2899SCharles.Forsyth } 55*37da2899SCharles.Forsyth 56*37da2899SCharles.Forsyth wmreq := chan of (string, chan of (string, ref Wmcontext)); 57*37da2899SCharles.Forsyth join := chan of (ref Client, chan of string); 58*37da2899SCharles.Forsyth req := chan of (ref Client, array of byte, Sys->Rwrite); 59*37da2899SCharles.Forsyth spawn wm(ctlio, wmreq, join, req); 60*37da2899SCharles.Forsyth return (wmreq, join, req); 61*37da2899SCharles.Forsyth} 62*37da2899SCharles.Forsyth 63*37da2899SCharles.Forsythwm(ctlio: ref Sys->FileIO, 64*37da2899SCharles.Forsyth wmreq: chan of (string, chan of (string, ref Wmcontext)), 65*37da2899SCharles.Forsyth join: chan of (ref Client, chan of string), 66*37da2899SCharles.Forsyth req: chan of (ref Client, array of byte, Sys->Rwrite)) 67*37da2899SCharles.Forsyth{ 68*37da2899SCharles.Forsyth clients: array of ref Client; 69*37da2899SCharles.Forsyth 70*37da2899SCharles.Forsyth for(;;)alt{ 71*37da2899SCharles.Forsyth (cmd, rc) := <-wmreq => 72*37da2899SCharles.Forsyth token := int cmd; 73*37da2899SCharles.Forsyth for(i := 0; i < len clients; i++) 74*37da2899SCharles.Forsyth if(clients[i] != nil && clients[i].token == token) 75*37da2899SCharles.Forsyth break; 76*37da2899SCharles.Forsyth 77*37da2899SCharles.Forsyth if(i == len clients){ 78*37da2899SCharles.Forsyth spawn senderror(rc, "not found"); 79*37da2899SCharles.Forsyth break; 80*37da2899SCharles.Forsyth } 81*37da2899SCharles.Forsyth c := clients[i]; 82*37da2899SCharles.Forsyth if(c.stop != nil){ 83*37da2899SCharles.Forsyth spawn senderror(rc, "already started"); 84*37da2899SCharles.Forsyth break; 85*37da2899SCharles.Forsyth } 86*37da2899SCharles.Forsyth ok := chan of string; 87*37da2899SCharles.Forsyth join <-= (c, ok); 88*37da2899SCharles.Forsyth if((e := <-ok) != nil){ 89*37da2899SCharles.Forsyth spawn senderror(rc, e); 90*37da2899SCharles.Forsyth break; 91*37da2899SCharles.Forsyth } 92*37da2899SCharles.Forsyth c.stop = chan of int; 93*37da2899SCharles.Forsyth spawn childminder(c, rc); 94*37da2899SCharles.Forsyth 95*37da2899SCharles.Forsyth (nil, nbytes, fid, rc) := <-ctlio.read => 96*37da2899SCharles.Forsyth if(rc == nil) 97*37da2899SCharles.Forsyth break; 98*37da2899SCharles.Forsyth c := findfid(clients, fid); 99*37da2899SCharles.Forsyth if(c == nil){ 100*37da2899SCharles.Forsyth c = ref Client( 101*37da2899SCharles.Forsyth chan of int, 102*37da2899SCharles.Forsyth chan of ref Draw->Pointer, 103*37da2899SCharles.Forsyth chan of string, 104*37da2899SCharles.Forsyth nil, 105*37da2899SCharles.Forsyth 0, 106*37da2899SCharles.Forsyth nil, 107*37da2899SCharles.Forsyth nil, 108*37da2899SCharles.Forsyth nil, 109*37da2899SCharles.Forsyth 110*37da2899SCharles.Forsyth chan of (ref Point, ref Image, chan of int), 111*37da2899SCharles.Forsyth -1, 112*37da2899SCharles.Forsyth fid, 113*37da2899SCharles.Forsyth fid, # token; XXX could be random integer + fid 114*37da2899SCharles.Forsyth newwmcontext() 115*37da2899SCharles.Forsyth ); 116*37da2899SCharles.Forsyth clients = addclient(clients, c); 117*37da2899SCharles.Forsyth } 118*37da2899SCharles.Forsyth alt{ 119*37da2899SCharles.Forsyth rc <-= (sys->aprint("%d", c.token), nil) => ; 120*37da2899SCharles.Forsyth * => ; 121*37da2899SCharles.Forsyth } 122*37da2899SCharles.Forsyth (nil, data, fid, wc) := <-ctlio.write => 123*37da2899SCharles.Forsyth c := findfid(clients, fid); 124*37da2899SCharles.Forsyth if(wc != nil){ 125*37da2899SCharles.Forsyth if(c == nil){ 126*37da2899SCharles.Forsyth alt{ 127*37da2899SCharles.Forsyth wc <-= (0, "must read first") => ; 128*37da2899SCharles.Forsyth * => ; 129*37da2899SCharles.Forsyth } 130*37da2899SCharles.Forsyth break; 131*37da2899SCharles.Forsyth } 132*37da2899SCharles.Forsyth req <-= (c, data, wc); 133*37da2899SCharles.Forsyth }else if(c != nil){ 134*37da2899SCharles.Forsyth req <-= (c, nil, nil); 135*37da2899SCharles.Forsyth delclient(clients, c); 136*37da2899SCharles.Forsyth } 137*37da2899SCharles.Forsyth } 138*37da2899SCharles.Forsyth} 139*37da2899SCharles.Forsyth 140*37da2899SCharles.Forsyth# buffer all events between a window manager and 141*37da2899SCharles.Forsyth# a client, so that one recalcitrant child can't 142*37da2899SCharles.Forsyth# clog the whole system. 143*37da2899SCharles.Forsythchildminder(c: ref Client, rc: chan of (string, ref Wmcontext)) 144*37da2899SCharles.Forsyth{ 145*37da2899SCharles.Forsyth wmctxt := c.wmctxt; 146*37da2899SCharles.Forsyth 147*37da2899SCharles.Forsyth dummykbd := chan of int; 148*37da2899SCharles.Forsyth dummyptr := chan of ref Pointer; 149*37da2899SCharles.Forsyth dummyimg := chan of ref Image; 150*37da2899SCharles.Forsyth dummyctl := chan of string; 151*37da2899SCharles.Forsyth 152*37da2899SCharles.Forsyth kbdq := ref Iqueue; 153*37da2899SCharles.Forsyth ptrq := ref Ptrqueue; 154*37da2899SCharles.Forsyth ctlq := ref Squeue; 155*37da2899SCharles.Forsyth 156*37da2899SCharles.Forsyth Imgnone, Imgsend, Imgsendnil1, Imgsendnil2, Imgorigin: con iota; 157*37da2899SCharles.Forsyth img, sendimg: ref Image; 158*37da2899SCharles.Forsyth imgorigin: Point; 159*37da2899SCharles.Forsyth imgstate := Imgnone; 160*37da2899SCharles.Forsyth 161*37da2899SCharles.Forsyth # send reply to client, but make sure we don't block. 162*37da2899SCharles.ForsythReply: 163*37da2899SCharles.Forsyth for(;;) alt{ 164*37da2899SCharles.Forsyth rc <-= (nil, ref *wmctxt) => 165*37da2899SCharles.Forsyth break Reply; 166*37da2899SCharles.Forsyth <-c.stop => 167*37da2899SCharles.Forsyth exit; 168*37da2899SCharles.Forsyth key := <-c.kbd => 169*37da2899SCharles.Forsyth kbdq.put(key); 170*37da2899SCharles.Forsyth ptr := <-c.ptr => 171*37da2899SCharles.Forsyth ptrq.put(ptr); 172*37da2899SCharles.Forsyth ctl := <-c.ctl => 173*37da2899SCharles.Forsyth ctlq.put(ctl); 174*37da2899SCharles.Forsyth } 175*37da2899SCharles.Forsyth 176*37da2899SCharles.Forsyth for(;;){ 177*37da2899SCharles.Forsyth outkbd := dummykbd; 178*37da2899SCharles.Forsyth key := -1; 179*37da2899SCharles.Forsyth if(kbdq.nonempty()){ 180*37da2899SCharles.Forsyth key = kbdq.peek(); 181*37da2899SCharles.Forsyth outkbd = wmctxt.kbd; 182*37da2899SCharles.Forsyth } 183*37da2899SCharles.Forsyth 184*37da2899SCharles.Forsyth outptr := dummyptr; 185*37da2899SCharles.Forsyth ptr: ref Pointer; 186*37da2899SCharles.Forsyth if(ptrq.nonempty()){ 187*37da2899SCharles.Forsyth ptr = ptrq.peek(); 188*37da2899SCharles.Forsyth outptr = wmctxt.ptr; 189*37da2899SCharles.Forsyth } 190*37da2899SCharles.Forsyth 191*37da2899SCharles.Forsyth outctl := dummyctl; 192*37da2899SCharles.Forsyth ctl: string; 193*37da2899SCharles.Forsyth if(ctlq.nonempty()){ 194*37da2899SCharles.Forsyth ctl = ctlq.peek(); 195*37da2899SCharles.Forsyth outctl = wmctxt.ctl; 196*37da2899SCharles.Forsyth } 197*37da2899SCharles.Forsyth 198*37da2899SCharles.Forsyth outimg := dummyimg; 199*37da2899SCharles.Forsyth case imgstate{ 200*37da2899SCharles.Forsyth Imgsend => 201*37da2899SCharles.Forsyth outimg = wmctxt.images; 202*37da2899SCharles.Forsyth sendimg = img; 203*37da2899SCharles.Forsyth Imgsendnil1 or 204*37da2899SCharles.Forsyth Imgsendnil2 or 205*37da2899SCharles.Forsyth Imgorigin => 206*37da2899SCharles.Forsyth outimg = wmctxt.images; 207*37da2899SCharles.Forsyth sendimg = nil; 208*37da2899SCharles.Forsyth } 209*37da2899SCharles.Forsyth 210*37da2899SCharles.Forsyth alt{ 211*37da2899SCharles.Forsyth outkbd <-= key => 212*37da2899SCharles.Forsyth kbdq.get(); 213*37da2899SCharles.Forsyth outptr <-= ptr => 214*37da2899SCharles.Forsyth ptrq.get(); 215*37da2899SCharles.Forsyth outctl <-= ctl => 216*37da2899SCharles.Forsyth ctlq.get(); 217*37da2899SCharles.Forsyth outimg <-= sendimg => 218*37da2899SCharles.Forsyth case imgstate{ 219*37da2899SCharles.Forsyth Imgsend => 220*37da2899SCharles.Forsyth imgstate = Imgnone; 221*37da2899SCharles.Forsyth img = sendimg = nil; 222*37da2899SCharles.Forsyth Imgsendnil1 => 223*37da2899SCharles.Forsyth imgstate = Imgsendnil2; 224*37da2899SCharles.Forsyth Imgsendnil2 => 225*37da2899SCharles.Forsyth imgstate = Imgnone; 226*37da2899SCharles.Forsyth Imgorigin => 227*37da2899SCharles.Forsyth if(img.origin(imgorigin, imgorigin) == -1){ 228*37da2899SCharles.Forsyth # XXX what can we do about this? there's no way at the moment 229*37da2899SCharles.Forsyth # of getting the information about the origin failure back to the wm, 230*37da2899SCharles.Forsyth # so we end up with an inconsistent window position. 231*37da2899SCharles.Forsyth # if the window manager blocks while we got the sync from 232*37da2899SCharles.Forsyth # the client, then a client could block the whole window manager 233*37da2899SCharles.Forsyth # which is what we're trying to avoid. 234*37da2899SCharles.Forsyth # but there's no other time we could set the origin of the window, 235*37da2899SCharles.Forsyth # and not risk mucking up the window contents. 236*37da2899SCharles.Forsyth # the short answer is that running out of image space is Bad News. 237*37da2899SCharles.Forsyth } 238*37da2899SCharles.Forsyth imgstate = Imgsend; 239*37da2899SCharles.Forsyth } 240*37da2899SCharles.Forsyth 241*37da2899SCharles.Forsyth # XXX could mark the application as unresponding if any of these queues 242*37da2899SCharles.Forsyth # start growing too much. 243*37da2899SCharles.Forsyth ch := <-c.kbd => 244*37da2899SCharles.Forsyth kbdq.put(ch); 245*37da2899SCharles.Forsyth p := <-c.ptr => 246*37da2899SCharles.Forsyth if(p == nil) 247*37da2899SCharles.Forsyth ptrq.flush(); 248*37da2899SCharles.Forsyth else 249*37da2899SCharles.Forsyth ptrq.put(p); 250*37da2899SCharles.Forsyth e := <-c.ctl => 251*37da2899SCharles.Forsyth ctlq.put(e); 252*37da2899SCharles.Forsyth (o, i, reply) := <-c.images => 253*37da2899SCharles.Forsyth # can't queue multiple image requests. 254*37da2899SCharles.Forsyth if(imgstate != Imgnone) 255*37da2899SCharles.Forsyth reply <-= -1; 256*37da2899SCharles.Forsyth else { 257*37da2899SCharles.Forsyth # if the origin is being set, then we first send a nil image 258*37da2899SCharles.Forsyth # to indicate that this is happening, and then the 259*37da2899SCharles.Forsyth # image itself (reorigined). 260*37da2899SCharles.Forsyth # if a nil image is being set, then we 261*37da2899SCharles.Forsyth # send nil twice. 262*37da2899SCharles.Forsyth if(o != nil){ 263*37da2899SCharles.Forsyth imgorigin = *o; 264*37da2899SCharles.Forsyth imgstate = Imgorigin; 265*37da2899SCharles.Forsyth img = i; 266*37da2899SCharles.Forsyth }else if(i != nil){ 267*37da2899SCharles.Forsyth img = i; 268*37da2899SCharles.Forsyth imgstate = Imgsend; 269*37da2899SCharles.Forsyth }else 270*37da2899SCharles.Forsyth imgstate = Imgsendnil1; 271*37da2899SCharles.Forsyth reply <-= 0; 272*37da2899SCharles.Forsyth } 273*37da2899SCharles.Forsyth <-c.stop => 274*37da2899SCharles.Forsyth # XXX do we need to unblock channels, kill, etc.? 275*37da2899SCharles.Forsyth # we should perhaps drain the ctl output channel here 276*37da2899SCharles.Forsyth # if possible, exiting if it times out. 277*37da2899SCharles.Forsyth exit; 278*37da2899SCharles.Forsyth } 279*37da2899SCharles.Forsyth } 280*37da2899SCharles.Forsyth} 281*37da2899SCharles.Forsyth 282*37da2899SCharles.Forsythfindfid(clients: array of ref Client, fid: int): ref Client 283*37da2899SCharles.Forsyth{ 284*37da2899SCharles.Forsyth for(i := 0; i < len clients; i++) 285*37da2899SCharles.Forsyth if(clients[i] != nil && clients[i].fid == fid) 286*37da2899SCharles.Forsyth return clients[i]; 287*37da2899SCharles.Forsyth return nil; 288*37da2899SCharles.Forsyth} 289*37da2899SCharles.Forsyth 290*37da2899SCharles.Forsythaddclient(clients: array of ref Client, c: ref Client): array of ref Client 291*37da2899SCharles.Forsyth{ 292*37da2899SCharles.Forsyth for(i := 0; i < len clients; i++) 293*37da2899SCharles.Forsyth if(clients[i] == nil){ 294*37da2899SCharles.Forsyth clients[i] = c; 295*37da2899SCharles.Forsyth c.id = i; 296*37da2899SCharles.Forsyth return clients; 297*37da2899SCharles.Forsyth } 298*37da2899SCharles.Forsyth nc := array[len clients + 4] of ref Client; 299*37da2899SCharles.Forsyth nc[0:] = clients; 300*37da2899SCharles.Forsyth nc[len clients] = c; 301*37da2899SCharles.Forsyth c.id = len clients; 302*37da2899SCharles.Forsyth return nc; 303*37da2899SCharles.Forsyth} 304*37da2899SCharles.Forsyth 305*37da2899SCharles.Forsythdelclient(clients: array of ref Client, c: ref Client) 306*37da2899SCharles.Forsyth{ 307*37da2899SCharles.Forsyth clients[c.id] = nil; 308*37da2899SCharles.Forsyth} 309*37da2899SCharles.Forsyth 310*37da2899SCharles.Forsythsenderror(rc: chan of (string, ref Wmcontext), e: string) 311*37da2899SCharles.Forsyth{ 312*37da2899SCharles.Forsyth rc <-= (e, nil); 313*37da2899SCharles.Forsyth} 314*37da2899SCharles.Forsyth 315*37da2899SCharles.ForsythClient.window(c: self ref Client, tag: string): ref Window 316*37da2899SCharles.Forsyth{ 317*37da2899SCharles.Forsyth for (w := c.wins; w != nil; w = tl w) 318*37da2899SCharles.Forsyth if((hd w).tag == tag) 319*37da2899SCharles.Forsyth return hd w; 320*37da2899SCharles.Forsyth return nil; 321*37da2899SCharles.Forsyth} 322*37da2899SCharles.Forsyth 323*37da2899SCharles.ForsythClient.image(c: self ref Client, tag: string): ref Draw->Image 324*37da2899SCharles.Forsyth{ 325*37da2899SCharles.Forsyth w := c.window(tag); 326*37da2899SCharles.Forsyth if(w != nil) 327*37da2899SCharles.Forsyth return w.img; 328*37da2899SCharles.Forsyth return nil; 329*37da2899SCharles.Forsyth} 330*37da2899SCharles.Forsyth 331*37da2899SCharles.ForsythClient.setimage(c: self ref Client, tag: string, img: ref Draw->Image): int 332*37da2899SCharles.Forsyth{ 333*37da2899SCharles.Forsyth # if img is nil, remove window from list. 334*37da2899SCharles.Forsyth if(img == nil){ 335*37da2899SCharles.Forsyth # usual case: 336*37da2899SCharles.Forsyth if(c.wins != nil && (hd c.wins).tag == tag){ 337*37da2899SCharles.Forsyth c.wins = tl c.wins; 338*37da2899SCharles.Forsyth return -1; 339*37da2899SCharles.Forsyth } 340*37da2899SCharles.Forsyth nw: list of ref Window; 341*37da2899SCharles.Forsyth for (w := c.wins; w != nil; w = tl w) 342*37da2899SCharles.Forsyth if((hd w).tag != tag) 343*37da2899SCharles.Forsyth nw = hd w :: nw; 344*37da2899SCharles.Forsyth c.wins = nil; 345*37da2899SCharles.Forsyth for(; nw != nil; nw = tl nw) 346*37da2899SCharles.Forsyth c.wins = hd nw :: c.wins; 347*37da2899SCharles.Forsyth return -1; 348*37da2899SCharles.Forsyth } 349*37da2899SCharles.Forsyth for(w := c.wins; w != nil; w = tl w) 350*37da2899SCharles.Forsyth if((hd w).tag == tag) 351*37da2899SCharles.Forsyth break; 352*37da2899SCharles.Forsyth win: ref Window; 353*37da2899SCharles.Forsyth if(w != nil) 354*37da2899SCharles.Forsyth win = hd w; 355*37da2899SCharles.Forsyth else{ 356*37da2899SCharles.Forsyth win = ref Window(tag, ZR, nil); 357*37da2899SCharles.Forsyth c.wins = win :: c.wins; 358*37da2899SCharles.Forsyth } 359*37da2899SCharles.Forsyth win.img = img; 360*37da2899SCharles.Forsyth win.r = img.r; # save so clients can set logical origin 361*37da2899SCharles.Forsyth rc := chan of int; 362*37da2899SCharles.Forsyth c.images <-= (nil, img, rc); 363*37da2899SCharles.Forsyth return <-rc; 364*37da2899SCharles.Forsyth} 365*37da2899SCharles.Forsyth 366*37da2899SCharles.Forsyth# tell a client about a window that's moved to screen coord o. 367*37da2899SCharles.ForsythClient.setorigin(c: self ref Client, tag: string, o: Draw->Point): int 368*37da2899SCharles.Forsyth{ 369*37da2899SCharles.Forsyth w := c.window(tag); 370*37da2899SCharles.Forsyth if(w == nil) 371*37da2899SCharles.Forsyth return -1; 372*37da2899SCharles.Forsyth img := w.img; 373*37da2899SCharles.Forsyth if(img == nil) 374*37da2899SCharles.Forsyth return -1; 375*37da2899SCharles.Forsyth rc := chan of int; 376*37da2899SCharles.Forsyth c.images <-= (ref o, w.img, rc); 377*37da2899SCharles.Forsyth if(<-rc != -1){ 378*37da2899SCharles.Forsyth w.r = (o, o.add(img.r.size())); 379*37da2899SCharles.Forsyth return 0; 380*37da2899SCharles.Forsyth } 381*37da2899SCharles.Forsyth return -1; 382*37da2899SCharles.Forsyth} 383*37da2899SCharles.Forsyth 384*37da2899SCharles.Forsythclientimages(c: ref Client): array of ref Image 385*37da2899SCharles.Forsyth{ 386*37da2899SCharles.Forsyth a := array[len c.wins] of ref Draw->Image; 387*37da2899SCharles.Forsyth i := 0; 388*37da2899SCharles.Forsyth for(w := c.wins; w != nil; w = tl w) 389*37da2899SCharles.Forsyth if((hd w).img != nil) 390*37da2899SCharles.Forsyth a[i++] = (hd w).img; 391*37da2899SCharles.Forsyth return a[0:i]; 392*37da2899SCharles.Forsyth} 393*37da2899SCharles.Forsyth 394*37da2899SCharles.ForsythClient.top(c: self ref Client) 395*37da2899SCharles.Forsyth{ 396*37da2899SCharles.Forsyth imgs := clientimages(c); 397*37da2899SCharles.Forsyth if(len imgs > 0) 398*37da2899SCharles.Forsyth imgs[0].screen.top(imgs); 399*37da2899SCharles.Forsyth 400*37da2899SCharles.Forsyth if(zorder == c) 401*37da2899SCharles.Forsyth return; 402*37da2899SCharles.Forsyth 403*37da2899SCharles.Forsyth prev: ref Client; 404*37da2899SCharles.Forsyth for(z := zorder; z != nil; (prev, z) = (z, z.znext)) 405*37da2899SCharles.Forsyth if(z == c) 406*37da2899SCharles.Forsyth break; 407*37da2899SCharles.Forsyth if(prev != nil) 408*37da2899SCharles.Forsyth prev.znext = c.znext; 409*37da2899SCharles.Forsyth c.znext = zorder; 410*37da2899SCharles.Forsyth zorder = c; 411*37da2899SCharles.Forsyth} 412*37da2899SCharles.Forsyth 413*37da2899SCharles.ForsythClient.bottom(c: self ref Client) 414*37da2899SCharles.Forsyth{ 415*37da2899SCharles.Forsyth if(c.znext == nil) 416*37da2899SCharles.Forsyth return; 417*37da2899SCharles.Forsyth imgs := clientimages(c); 418*37da2899SCharles.Forsyth if(len imgs > 0) 419*37da2899SCharles.Forsyth imgs[0].screen.bottom(imgs); 420*37da2899SCharles.Forsyth prev: ref Client; 421*37da2899SCharles.Forsyth for(z := zorder; z != nil; (prev, z) = (z, z.znext)) 422*37da2899SCharles.Forsyth if(z == c) 423*37da2899SCharles.Forsyth break; 424*37da2899SCharles.Forsyth if(prev != nil) 425*37da2899SCharles.Forsyth prev.znext = c.znext; 426*37da2899SCharles.Forsyth else 427*37da2899SCharles.Forsyth zorder = c.znext; 428*37da2899SCharles.Forsyth z = c.znext; 429*37da2899SCharles.Forsyth c.znext = nil; 430*37da2899SCharles.Forsyth for(; z != nil; (prev, z) = (z, z.znext)) 431*37da2899SCharles.Forsyth ; 432*37da2899SCharles.Forsyth if(prev != nil) 433*37da2899SCharles.Forsyth prev.znext = c; 434*37da2899SCharles.Forsyth else 435*37da2899SCharles.Forsyth zorder = c; 436*37da2899SCharles.Forsyth} 437*37da2899SCharles.Forsyth 438*37da2899SCharles.ForsythClient.hide(nil: self ref Client) 439*37da2899SCharles.Forsyth{ 440*37da2899SCharles.Forsyth} 441*37da2899SCharles.Forsyth 442*37da2899SCharles.ForsythClient.unhide(nil: self ref Client) 443*37da2899SCharles.Forsyth{ 444*37da2899SCharles.Forsyth} 445*37da2899SCharles.Forsyth 446*37da2899SCharles.ForsythClient.remove(c: self ref Client) 447*37da2899SCharles.Forsyth{ 448*37da2899SCharles.Forsyth prev: ref Client; 449*37da2899SCharles.Forsyth for(z := zorder; z != nil; (prev, z) = (z, z.znext)) 450*37da2899SCharles.Forsyth if(z == c) 451*37da2899SCharles.Forsyth break; 452*37da2899SCharles.Forsyth if(z == nil) 453*37da2899SCharles.Forsyth return; 454*37da2899SCharles.Forsyth if(prev != nil) 455*37da2899SCharles.Forsyth prev.znext = z.znext; 456*37da2899SCharles.Forsyth else if(z != nil) 457*37da2899SCharles.Forsyth zorder = zorder.znext; 458*37da2899SCharles.Forsyth} 459*37da2899SCharles.Forsyth 460*37da2899SCharles.Forsythfind(p: Draw->Point): ref Client 461*37da2899SCharles.Forsyth{ 462*37da2899SCharles.Forsyth for(z := zorder; z != nil; z = z.znext) 463*37da2899SCharles.Forsyth if(z.contains(p)) 464*37da2899SCharles.Forsyth return z; 465*37da2899SCharles.Forsyth return nil; 466*37da2899SCharles.Forsyth} 467*37da2899SCharles.Forsyth 468*37da2899SCharles.Forsythtop(): ref Client 469*37da2899SCharles.Forsyth{ 470*37da2899SCharles.Forsyth return zorder; 471*37da2899SCharles.Forsyth} 472*37da2899SCharles.Forsyth 473*37da2899SCharles.ForsythClient.contains(c: self ref Client, p: Point): int 474*37da2899SCharles.Forsyth{ 475*37da2899SCharles.Forsyth for(w := c.wins; w != nil; w = tl w) 476*37da2899SCharles.Forsyth if((hd w).r.contains(p)) 477*37da2899SCharles.Forsyth return 1; 478*37da2899SCharles.Forsyth return 0; 479*37da2899SCharles.Forsyth} 480*37da2899SCharles.Forsyth 481*37da2899SCharles.Forsythr2s(r: Rect): string 482*37da2899SCharles.Forsyth{ 483*37da2899SCharles.Forsyth return string r.min.x + " " + string r.min.y + " " + 484*37da2899SCharles.Forsyth string r.max.x + " " + string r.max.y; 485*37da2899SCharles.Forsyth} 486*37da2899SCharles.Forsyth 487*37da2899SCharles.Forsythnewwmcontext(): ref Wmcontext 488*37da2899SCharles.Forsyth{ 489*37da2899SCharles.Forsyth return ref Wmcontext( 490*37da2899SCharles.Forsyth chan of int, 491*37da2899SCharles.Forsyth chan of ref Pointer, 492*37da2899SCharles.Forsyth chan of string, 493*37da2899SCharles.Forsyth nil, 494*37da2899SCharles.Forsyth chan of ref Image, 495*37da2899SCharles.Forsyth nil, 496*37da2899SCharles.Forsyth nil 497*37da2899SCharles.Forsyth ); 498*37da2899SCharles.Forsyth} 499*37da2899SCharles.Forsyth 500*37da2899SCharles.ForsythIqueue.put(q: self ref Iqueue, s: int) 501*37da2899SCharles.Forsyth{ 502*37da2899SCharles.Forsyth q.t = s :: q.t; 503*37da2899SCharles.Forsyth} 504*37da2899SCharles.ForsythIqueue.get(q: self ref Iqueue): int 505*37da2899SCharles.Forsyth{ 506*37da2899SCharles.Forsyth s := -1; 507*37da2899SCharles.Forsyth if(q.h == nil){ 508*37da2899SCharles.Forsyth for(t := q.t; t != nil; t = tl t) 509*37da2899SCharles.Forsyth q.h = hd t :: q.h; 510*37da2899SCharles.Forsyth q.t = nil; 511*37da2899SCharles.Forsyth } 512*37da2899SCharles.Forsyth if(q.h != nil){ 513*37da2899SCharles.Forsyth s = hd q.h; 514*37da2899SCharles.Forsyth q.h = tl q.h; 515*37da2899SCharles.Forsyth } 516*37da2899SCharles.Forsyth return s; 517*37da2899SCharles.Forsyth} 518*37da2899SCharles.ForsythIqueue.peek(q: self ref Iqueue): int 519*37da2899SCharles.Forsyth{ 520*37da2899SCharles.Forsyth s := -1; 521*37da2899SCharles.Forsyth if (q.h == nil && q.t == nil) 522*37da2899SCharles.Forsyth return s; 523*37da2899SCharles.Forsyth s = q.get(); 524*37da2899SCharles.Forsyth q.h = s :: q.h; 525*37da2899SCharles.Forsyth return s; 526*37da2899SCharles.Forsyth} 527*37da2899SCharles.ForsythIqueue.nonempty(q: self ref Iqueue): int 528*37da2899SCharles.Forsyth{ 529*37da2899SCharles.Forsyth return q.h != nil || q.t != nil; 530*37da2899SCharles.Forsyth} 531*37da2899SCharles.Forsyth 532*37da2899SCharles.Forsyth 533*37da2899SCharles.ForsythSqueue.put(q: self ref Squeue, s: string) 534*37da2899SCharles.Forsyth{ 535*37da2899SCharles.Forsyth q.t = s :: q.t; 536*37da2899SCharles.Forsyth} 537*37da2899SCharles.ForsythSqueue.get(q: self ref Squeue): string 538*37da2899SCharles.Forsyth{ 539*37da2899SCharles.Forsyth s: string; 540*37da2899SCharles.Forsyth if(q.h == nil){ 541*37da2899SCharles.Forsyth for(t := q.t; t != nil; t = tl t) 542*37da2899SCharles.Forsyth q.h = hd t :: q.h; 543*37da2899SCharles.Forsyth q.t = nil; 544*37da2899SCharles.Forsyth } 545*37da2899SCharles.Forsyth if(q.h != nil){ 546*37da2899SCharles.Forsyth s = hd q.h; 547*37da2899SCharles.Forsyth q.h = tl q.h; 548*37da2899SCharles.Forsyth } 549*37da2899SCharles.Forsyth return s; 550*37da2899SCharles.Forsyth} 551*37da2899SCharles.ForsythSqueue.peek(q: self ref Squeue): string 552*37da2899SCharles.Forsyth{ 553*37da2899SCharles.Forsyth s: string; 554*37da2899SCharles.Forsyth if (q.h == nil && q.t == nil) 555*37da2899SCharles.Forsyth return s; 556*37da2899SCharles.Forsyth s = q.get(); 557*37da2899SCharles.Forsyth q.h = s :: q.h; 558*37da2899SCharles.Forsyth return s; 559*37da2899SCharles.Forsyth} 560*37da2899SCharles.ForsythSqueue.nonempty(q: self ref Squeue): int 561*37da2899SCharles.Forsyth{ 562*37da2899SCharles.Forsyth return q.h != nil || q.t != nil; 563*37da2899SCharles.Forsyth} 564*37da2899SCharles.Forsyth 565*37da2899SCharles.ForsythPtrqueue.put(q: self ref Ptrqueue, s: ref Pointer) 566*37da2899SCharles.Forsyth{ 567*37da2899SCharles.Forsyth if(q.last != nil && s.buttons == q.last.buttons) 568*37da2899SCharles.Forsyth *q.last = *s; 569*37da2899SCharles.Forsyth else{ 570*37da2899SCharles.Forsyth q.t = s :: q.t; 571*37da2899SCharles.Forsyth q.last = s; 572*37da2899SCharles.Forsyth } 573*37da2899SCharles.Forsyth} 574*37da2899SCharles.ForsythPtrqueue.get(q: self ref Ptrqueue): ref Pointer 575*37da2899SCharles.Forsyth{ 576*37da2899SCharles.Forsyth s: ref Pointer; 577*37da2899SCharles.Forsyth h := q.h; 578*37da2899SCharles.Forsyth if(h == nil){ 579*37da2899SCharles.Forsyth for(t := q.t; t != nil; t = tl t) 580*37da2899SCharles.Forsyth h = hd t :: h; 581*37da2899SCharles.Forsyth q.t = nil; 582*37da2899SCharles.Forsyth } 583*37da2899SCharles.Forsyth if(h != nil){ 584*37da2899SCharles.Forsyth s = hd h; 585*37da2899SCharles.Forsyth h = tl h; 586*37da2899SCharles.Forsyth if(h == nil) 587*37da2899SCharles.Forsyth q.last = nil; 588*37da2899SCharles.Forsyth } 589*37da2899SCharles.Forsyth q.h = h; 590*37da2899SCharles.Forsyth return s; 591*37da2899SCharles.Forsyth} 592*37da2899SCharles.ForsythPtrqueue.peek(q: self ref Ptrqueue): ref Pointer 593*37da2899SCharles.Forsyth{ 594*37da2899SCharles.Forsyth s: ref Pointer; 595*37da2899SCharles.Forsyth if (q.h == nil && q.t == nil) 596*37da2899SCharles.Forsyth return s; 597*37da2899SCharles.Forsyth t := q.last; 598*37da2899SCharles.Forsyth s = q.get(); 599*37da2899SCharles.Forsyth q.h = s :: q.h; 600*37da2899SCharles.Forsyth q.last = t; 601*37da2899SCharles.Forsyth return s; 602*37da2899SCharles.Forsyth} 603*37da2899SCharles.ForsythPtrqueue.nonempty(q: self ref Ptrqueue): int 604*37da2899SCharles.Forsyth{ 605*37da2899SCharles.Forsyth return q.h != nil || q.t != nil; 606*37da2899SCharles.Forsyth} 607*37da2899SCharles.ForsythPtrqueue.flush(q: self ref Ptrqueue) 608*37da2899SCharles.Forsyth{ 609*37da2899SCharles.Forsyth q.h = q.t = nil; 610*37da2899SCharles.Forsyth} 611