commit - 4af386f434d5ca3de733951d4f73dd134e879cc2
commit + 161060a46346fa0beeb48b55ed28b2cd330bc4e8
blob - 8013efa56f01f1dc95427eb7498c5545b6b2beb6
blob + 807b8e743aa79f2b6c01b572d420c770b1f5a057
--- src/libdraw/Makefile
+++ src/libdraw/Makefile
x11-mouse.$O\
x11-pixelbits.$O\
x11-unload.$O\
+ x11-wsys.$O\
devdraw.$O\
unix.$O\
blob - 41b30620f22e982acc7c164d41bb2a747056d663
blob + 1b19fc1c42a98bf81368b1a519134304a3175651
--- src/libdraw/arith.c
+++ src/libdraw/arith.c
CMAP8,
};
-int log2[] = { -1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, 4 /* BUG */, -1, -1, -1, -1, -1, -1, -1, 5 };
-
u32int
setalpha(u32int color, uchar alpha)
{
blob - b0036385dbcfa82285fbf70d45dddebb0d6cb011
blob + f4749867140703b0d41a0343a126fc6c1131414a
--- src/libdraw/devdraw.c
+++ src/libdraw/devdraw.c
_initdisplaymemimage(Display *d, Memimage *m)
{
screenimage = m;
+ m->screenref = 1;
client0 = mallocz(sizeof(Client), 1);
if(client0 == nil){
fprint(2, "initdraw: allocating client0: out of memory");
* about the resize through external means, so all we
* need to do is this assignment.
*/
+ Memimage *om;
+
+ qlock(&sdraw.lk);
+ om = screenimage;
screenimage = m;
+ m->screenref = 1;
+ if(om && --om->screenref == 0){
+ _freememimage(om);
+ }
+ qunlock(&sdraw.lk);
}
static
d->name = 0;
d->vers = 0;
d->image = i;
+ if(i->screenref)
+ ++i->screenref;
d->nfchar = 0;
d->fchar = 0;
d->fromname = 0;
drawfreedimage(dimage->fromname);
goto Return;
}
- //if(dimage->image == screenimage) /* don't free the display */
- // goto Return;
ds = dimage->dscreen;
+ l = dimage->image;
if(ds){
- l = dimage->image;
if(l->data == screenimage->data)
addflush(l->layer->screenr);
if(l->layer->refreshfn == drawrefresh) /* else true owner will clean up */
else
memlfree(l);
drawfreedscreen(ds);
- }else
- freememimage(dimage->image);
+ }else{
+ if(l->screenref==0)
+ freememimage(l);
+ else if(--l->screenref==0)
+ _freememimage(l);
+ }
Return:
free(dimage->fchar);
free(dimage);
{
int inbuf;
+ qlock(&sdraw.lk);
inbuf = d->obufp - d->obuf;
if(n > inbuf)
n = inbuf;
if(inbuf)
memmove(d->obuf, d->obufp-inbuf, inbuf);
d->obufp = d->obuf+inbuf;
+ qunlock(&sdraw.lk);
return n;
}
Refreshfn reffn;
Refx *refx;
+ qlock(&sdraw.lk);
d->obufp = d->obuf;
a = v;
m = 0;
continue;
}
}
+ qunlock(&sdraw.lk);
return oldn - n;
Enodrawimage:
Eshortdraw:
err = "short draw message";
goto error;
+/*
Eshortread:
err = "draw read too short";
goto error;
+*/
Eimageexists:
err = "image id in use";
goto error;
Eindex:
err = "character index out of range";
goto error;
+/*
Enoclient:
err = "no such draw client";
goto error;
Enameused:
err = "image name in use";
goto error;
+*/
Enoname:
err = "no image with that name";
goto error;
goto error;
error:
- drawerror(display, err);
+ werrstr("%s", err);
+ qunlock(&sdraw.lk);
return -1;
}
blob - 632e82385919aeab2525903b0cb38df0591f09cd
blob + 7053c171c6837abc070e5a995598ee503f8e65a7
--- src/libdraw/md-line.c
+++ src/libdraw/md-line.c
Arrow3 = 3,
};
+/*
static
int
lmin(int a, int b)
return a;
return b;
}
+*/
static
int
blob - dc16e379b744c75f93ae55af57276e668c5fa783
blob + e9fa3f849b3460c32388918c7ca23cd73d194ba8
--- src/libdraw/openfont.c
+++ src/libdraw/openfont.c
#include <libc.h>
#include <draw.h>
+extern vlong _drawflength(int);
+
Font*
openfont(Display *d, char *name)
{
if(fd < 0)
return 0;
- n = flength(fd);
+ n = _drawflength(fd);
buf = malloc(n+1);
if(buf == 0){
close(fd);
blob - bcb4e3a1ef7f49020f50ab0852c4501683de9d5d
blob + bf397cb5b5f18b964e7060ca4be45d0e7bcf7bb8
--- src/libdraw/subfontname.c
+++ src/libdraw/subfontname.c
if(maxdepth > 8)
maxdepth = 8;
- for(i=log2[maxdepth]; i>=0; i--){
+ for(i=3; i>=0; i--){
+ if((1<<i) > maxdepth)
+ continue;
/* try i-bit grey */
snprint(tmp2, sizeof tmp2, "%s.%d", t, i);
if(access(tmp2, AREAD) == 0)
blob - 2203b0876e47137bc3ca1d18e7ce7e879f7e09db
blob + 491bc66c866c2ab163d1d8995f0f68820c48872a
--- src/libdraw/unix.c
+++ src/libdraw/unix.c
#include <draw.h>
vlong
-flength(int fd)
+_drawflength(int fd)
{
struct stat s;
blob - 19475c747818d4a7b05b110e632f7dc164d34729
blob + 458efc61fdee4de8974315802a1ecd8d0fc6a274
--- src/libdraw/x11-alloc.c
+++ src/libdraw/x11-alloc.c
}
/*
- * Allocate backing store. What we call a 32-bit image
- * the X server calls a 24-bit image.
+ * Allocate backing store.
*/
- d = m->depth;
+ if(chan == GREY1)
+ d = 1;
+ else
+ d = _x.depth;
if(pixmap != PMundef)
xm->pixmap = pixmap;
else
- xm->pixmap = XCreatePixmap(_x.display, _x.drawable,
- Dx(r), Dy(r), d==32 ? 24 : d);
+ xm->pixmap = XCreatePixmap(_x.display, _x.drawable, Dx(r), Dy(r), d);
/*
* We want to align pixels on word boundaries.
*/
- if(d == 24)
+ if(m->depth == 24)
offset = r.min.x&3;
else
offset = r.min.x&(31/m->depth);
/*
* Wrap our data in an XImage structure.
*/
- xi = XCreateImage(_x.display, _x.vis, d==32 ? 24 : d,
+ xi = XCreateImage(_x.display, _x.vis, d,
ZPixmap, 0, (char*)m->data->bdata, Dx(r), Dy(r),
32, m->width*sizeof(u32int));
if(xi == nil){
blob - ee91791d9794c4cb8aef91cc76f170d07047abed
blob + 97438740e899e297802ca550fcf6ef45aa59e4aa
--- src/libdraw/x11-draw.c
+++ src/libdraw/x11-draw.c
memimagedraw(Memimage *dst, Rectangle r, Memimage *src, Point sp,
Memimage *mask, Point mp, int op)
{
- int drew;
Memdrawparam *par;
if((par = _memimagedrawsetup(dst, r, src, sp, mask, mp, op)) == nil)
}
}else{
/* this doesn't work on rob's mac? */
+ return 0;
gc = _x.gcsimplesrc;
if(dst->chan == CMAP8 && _x.usetable)
sdval = _x.tox11[sdval];
blob - 85543e838e934f1288d01fba26ff0e372c20da09
blob + 28f6ae4009c89b8dcb73e4f4991a313c6ba6f4f7
--- src/libdraw/x11-init.c
+++ src/libdraw/x11-init.c
fprint(2, "cannot read screen info: %r\n");
abort();
}
-
+
n = _drawmsgread(d, info, sizeof info);
if(n != 12*12){
fprint(2, "short screen info\n");
{
char buf[200];
- print("X error: error_code=%d, request_code=%d, minor=%d\n",
- e->error_code, e->request_code, e->minor_code);
+ print("X error: error_code=%d, request_code=%d, minor=%d disp=%p\n",
+ e->error_code, e->request_code, e->minor_code, d);
XGetErrorText(d, e->error_code, buf, sizeof buf);
print("%s\n", buf);
return 0;
_x.usetable = 1;
}
else
+ if(XMatchVisualInfo(_x.display, xrootid, 15, TrueColor, &xvi)
+ || XMatchVisualInfo(_x.display, xrootid, 15, DirectColor, &xvi)){
+ _x.vis = xvi.visual;
+ _x.depth = 15;
+ _x.usetable = 1;
+ }
+ else
if(XMatchVisualInfo(_x.display, xrootid, 24, TrueColor, &xvi)
|| XMatchVisualInfo(_x.display, xrootid, 24, DirectColor, &xvi)){
_x.vis = xvi.visual;
break;
case 8:
_x.chan = CMAP8;
+ break;
+ case 15:
+ _x.chan = RGB15;
break;
case 16: /* how to tell RGB15? */
_x.chan = RGB16;
memset(&attr, 0, sizeof attr);
attr.colormap = _x.cmap;
- attr.background_pixel = 0;
+ attr.background_pixel = ~0;
attr.border_pixel = 0;
_x.drawable = XCreateWindow(
_x.display, /* display */
Dx(r), /* width */
Dy(r), /* height */
0, /* border width */
- _x.depth, /* depth */
+ DefaultDepthOfScreen(xscreen), /* depth */
InputOutput, /* class */
_x.vis, /* visual */
/* valuemask */
*/
_x.screenr = r;
_x.screenpm = XCreatePixmap(_x.display, _x.drawable, Dx(r), Dy(r), _x.depth);
+ _x.nextscreenpm = _x.screenpm;
_x.screenimage = xallocmemimage(r, _x.chan, _x.screenpm);
/*
XFlush(_x.display);
/*
- * Lots of display connections for various threads.
+ * Lots of display connections for various procs.
*/
_x.kbdcon = XOpenDisplay(NULL);
_x.mousecon = XOpenDisplay(NULL);
_x.snarfcon = XOpenDisplay(NULL);
+ if(0) fprint(2, "x: display=%p kbd=%p mouse=%p snarf=%p\n",
+ _x.display, _x.kbdcon, _x.mousecon, _x.snarfcon);
+
_x.black = xscreen->black_pixel;
_x.white = xscreen->white_pixel;
return _x.screenimage;
err0:
+fprint(2, "%r\n");
/*
* Should do a better job of cleaning up here.
*/
void
flushmemscreen(Rectangle r)
{
+ if(_x.nextscreenpm != _x.screenpm){
+ qlock(&_x.screenlock);
+ XSync(_x.display, False);
+ XFreePixmap(_x.display, _x.screenpm);
+ _x.screenpm = _x.nextscreenpm;
+ qunlock(&_x.screenlock);
+ }
+
if(r.min.x >= r.max.x || r.min.y >= r.max.y)
return;
XCopyArea(_x.display, _x.screenpm, _x.drawable, _x.gccopy, r.min.x, r.min.y,
XExposeEvent *xe;
Rectangle r;
+ qlock(&_x.screenlock);
+ if(_x.screenpm != _x.nextscreenpm){
+ qunlock(&_x.screenlock);
+ return;
+ }
xe = (XExposeEvent*)e;
r.min.x = xe->x;
r.min.y = xe->y;
r.max.y = xe->y+xe->height;
XCopyArea(xd, _x.screenpm, _x.drawable, _x.gccopy, r.min.x, r.min.y,
Dx(r), Dy(r), r.min.x, r.min.y);
- XFlush(xd);
+ XSync(xd, False);
+ qunlock(&_x.screenlock);
}
int
xconfigure(XEvent *e, XDisplay *xd)
{
+ Rectangle r;
XConfigureEvent *xe = (XConfigureEvent*)e;
if(xe->width == Dx(_x.screenr) && xe->height == Dy(_x.screenr))
return 0;
- _x.newscreenr = Rect(0, 0, xe->width, xe->height);
+ if(xe->width==0 || xe->height==0)
+ fprint(2, "ignoring resize to %dx%d\n", xe->width, xe->height);
+ r = Rect(0, 0, xe->width, xe->height);
+ qlock(&_x.screenlock);
+ if(_x.screenpm != _x.nextscreenpm){
+ XCopyArea(xd, _x.screenpm, _x.drawable, _x.gccopy, r.min.x, r.min.y,
+ Dx(r), Dy(r), r.min.x, r.min.y);
+ XSync(xd, False);
+ }
+ qunlock(&_x.screenlock);
+ _x.newscreenr = r;
return 1;
}
pixmap = XCreatePixmap(_x.display, _x.drawable, Dx(r), Dy(r), _x.depth);
m = xallocmemimage(r, _x.chan, pixmap);
- _x.screenpm = pixmap;
+ if(_x.nextscreenpm != _x.screenpm)
+ XFreePixmap(_x.display, _x.nextscreenpm);
+ _x.nextscreenpm = pixmap;
_x.screenr = r;
_drawreplacescreenimage(m);
return 1;
blob - 49ee3fbba8f20d2e01d7d7e6181d6d168e3a0100
blob + 35fd31ea2a07675971e1e83da45b975e003357f6
--- src/libdraw/x11-itrans.c
+++ src/libdraw/x11-itrans.c
XFreePixmap(_x.display, xsrc);
XFreePixmap(_x.display, xmask);
XFlush(_x.display);
+}
+
+struct {
+ char buf[SnarfSize];
+ QLock lk;
+} clip;
+
+char*
+xgetsnarf(XDisplay *xd)
+{
+ uchar *data, *xdata;
+ Atom type;
+ ulong len, lastlen, dummy;
+ int fmt, i;
+ XWindow w;
+
+ qlock(&clip.lk);
+ w = XGetSelectionOwner(xd, XA_PRIMARY);
+ if(w == _x.drawable){
+ data = (uchar*)strdup(clip.buf);
+ goto out;
+ }
+ if(w == None){
+ data = nil;
+ goto out;
+ }
+ /*
+ * We should be waiting for SelectionNotify here, but it might never
+ * come, and we have no way to time out. Instead, we will zero the
+ * property, request our buddy to fill it in for us, and wait until
+ * he's done.
+ */
+ XChangeProperty(xd, _x.drawable, XA_PRIMARY, XA_STRING, 8, PropModeReplace, (uchar*)"", 0);
+ XConvertSelection(xd, XA_PRIMARY, XA_STRING, None, _x.drawable, CurrentTime);
+ XFlush(xd);
+ lastlen = 0;
+ for(i=0; i<30; i++){
+ usleep(100*1000);
+ XGetWindowProperty(xd, _x.drawable, XA_STRING, 0, 0, 0, AnyPropertyType,
+ &type, &fmt, &dummy, &len, &data);
+ if(lastlen == len && len > 0)
+ break;
+ lastlen = len;
+ }
+ if(i == 30){
+ data = nil;
+ goto out;
+ }
+ /* get the property */
+ data = nil;
+ XGetWindowProperty(xd, _x.drawable, XA_STRING, 0, SnarfSize/4, 0,
+ AnyPropertyType, &type, &fmt, &len, &dummy, &xdata);
+ if(type != XA_STRING || len == 0){
+ if(xdata)
+ XFree(xdata);
+ data = nil;
+ }else{
+ if(xdata){
+ data = strdup((char*)xdata);
+ XFree(xdata);
+ }else
+ data = nil;
+ }
+out:
+ qunlock(&clip.lk);
+ return data;
}
+void
+xputsnarf(XDisplay *xd, char *data)
+{
+ if(strlen(data) >= SnarfSize)
+ return;
+ qlock(&clip.lk);
+ strcpy(clip.buf, data);
+ /*
+ * BUG: This is wrong. Instead, we should send an event to the
+ * mouse connection telling it to call XSetSelectionOwner.
+ */
+ XSetSelectionOwner(_x.mousecon, XA_PRIMARY, _x.drawable, CurrentTime);
+ XFlush(xd);
+ qunlock(&clip.lk);
+}
+
+int
+xselect(XEvent *e, XDisplay *xd)
+{
+ XEvent r;
+ XSelectionRequestEvent *xe;
+
+ memset(&r, 0, sizeof r);
+ xe = (XSelectionRequestEvent*)e;
+ if(1 || xe->target == XA_STRING){
+ qlock(&clip.lk);
+ XChangeProperty(xd, xe->requestor, xe->property, XA_STRING, 8,
+ PropModeReplace, (uchar*)clip.buf, strlen(clip.buf)+1);
+ qunlock(&clip.lk);
+ r.xselection.property = xe->property;
+ }else{
+ fprint(2, "asked for a %d\n", xe->target);
+ r.xselection.property = None;
+ }
+
+ r.xselection.display = xe->display;
+ /* r.xselection.property filled above */
+ r.xselection.target = xe->target;
+ r.xselection.type = SelectionNotify;
+ r.xselection.requestor = xe->requestor;
+ r.xselection.time = xe->time;
+ r.xselection.send_event = True;
+ r.xselection.selection = xe->selection;
+ XSendEvent(xd, xe->requestor, False, 0, &r);
+ XFlush(xd);
+ return 0;
+}
+
+void
+putsnarf(char *data)
+{
+ xputsnarf(_x.snarfcon, data);
+}
+
+char*
+getsnarf(void)
+{
+ return xgetsnarf(_x.snarfcon);
+}
+
blob - 188e52bf467d1fd352b4755cdd4f9f42d5aa2716
blob + 92b57814c987dd9e49e76ce9a33b158f1cf87ba7
--- src/libdraw/x11-keyboard.c
+++ src/libdraw/x11-keyboard.c
kc = arg;
threadsetname("kbdproc");
kc->pid = getpid();
+ XSelectInput(_x.kbdcon, _x.drawable, KeyPressMask);
for(;;){
- XSelectInput(_x.kbdcon, _x.drawable, KeyPressMask);
XWindowEvent(_x.kbdcon, _x.drawable, KeyPressMask, &xevent);
switch(xevent.type){
case KeyPress:
blob - 9fffe34e1046c51d5ba96f990ff6490d109f93d1
blob + 514926da652cc0da5517f6032477c6b8b80e78d1
--- src/libdraw/x11-memdraw.h
+++ src/libdraw/x11-memdraw.h
XDisplay *mousecon;
Rectangle newscreenr;
Memimage* screenimage;
+ QLock screenlock;
XDrawable screenpm;
+ XDrawable nextscreenpm;
Rectangle screenr;
XDisplay *snarfcon;
int toplan9[256];
extern void xfreexdata(Memimage*);
extern XImage *xgetxdata(Memimage*, Rectangle);
extern void xputxdata(Memimage*, Rectangle);
+extern void _initdisplaymemimage(Display*, Memimage*);
struct Mouse;
extern int xtoplan9mouse(XEvent*, struct Mouse*);
extern int xtoplan9kbd(XEvent*);
extern void xexpose(XEvent*, XDisplay*);
+extern int xselect(XEvent*, XDisplay*);
extern int xconfigure(XEvent*, XDisplay*);
extern void flushmemscreen(Rectangle);
extern void xmoveto(Point);
blob - c6a2685107163432d19f99a2ba4f5783a3997c8f
blob + 6b5b3922af805dd27d62e48c3fbc6a513fdc2b48
--- src/libdraw/x11-mouse.c
+++ src/libdraw/x11-mouse.c
_ioproc(void *arg)
{
int one;
+ ulong mask;
Mouse m;
Mousectl *mc;
XEvent xevent;
threadsetname("mouseproc");
memset(&m, 0, sizeof m);
mc->pid = getpid();
+ mask = MouseMask|ExposureMask|StructureNotifyMask;
+ XSelectInput(_x.mousecon, _x.drawable, mask);
for(;;){
- XSelectInput(_x.mousecon, _x.drawable, MouseMask|ExposureMask|StructureNotifyMask);
- XWindowEvent(_x.mousecon, _x.drawable, MouseMask|ExposureMask|StructureNotifyMask, &xevent);
+ XNextEvent(_x.mousecon, &xevent);
switch(xevent.type){
case Expose:
xexpose(&xevent, _x.mousecon);
if(xconfigure(&xevent, _x.mousecon))
nbsend(mc->resizec, &one);
continue;
+ case SelectionRequest:
+ xselect(&xevent, _x.mousecon);
+ continue;
case ButtonPress:
case ButtonRelease:
case MotionNotify: