aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/devdraw
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/devdraw')
-rw-r--r--src/cmd/devdraw/devdraw.c30
-rw-r--r--src/cmd/devdraw/devdraw.h28
-rw-r--r--src/cmd/devdraw/latin1.c39
-rw-r--r--src/cmd/devdraw/mac-screen.m43
-rw-r--r--src/cmd/devdraw/mklatinkbd.c2
-rw-r--r--src/cmd/devdraw/srv.c35
-rw-r--r--src/cmd/devdraw/x11-screen.c21
7 files changed, 140 insertions, 58 deletions
diff --git a/src/cmd/devdraw/devdraw.c b/src/cmd/devdraw/devdraw.c
index b4c373ad..234cdf1b 100644
--- a/src/cmd/devdraw/devdraw.c
+++ b/src/cmd/devdraw/devdraw.c
@@ -14,6 +14,8 @@
#include <drawfcall.h>
#include "devdraw.h"
+QLock drawlk;
+
static int drawuninstall(Client*, int);
static Memimage* drawinstall(Client*, int, Memimage*, DScreen*);
static void drawfreedimage(Client*, DImage*);
@@ -47,14 +49,14 @@ gfx_replacescreenimage(Client *c, Memimage *m)
*/
Memimage *om;
- qlock(&c->drawlk);
+ qlock(&drawlk);
om = c->screenimage;
c->screenimage = m;
m->screenref = 1;
if(om && --om->screenref == 0){
_freememimage(om);
}
- qunlock(&c->drawlk);
+ qunlock(&drawlk);
gfx_mouseresized(c);
}
@@ -142,9 +144,9 @@ addflush(Client *c, Rectangle r)
// and gfx thread might be blocked on drawlk trying to install a new screen
// during a resize.
rpc_gfxdrawunlock();
- qunlock(&c->drawlk);
- rpc_flush(c, fr);
- qlock(&c->drawlk);
+ qunlock(&drawlk);
+ c->impl->rpc_flush(c, fr);
+ qlock(&drawlk);
rpc_gfxdrawlock();
}
}
@@ -187,9 +189,9 @@ drawflush(Client *c)
// and gfx thread might be blocked on drawlk trying to install a new screen
// during a resize.
rpc_gfxdrawunlock();
- qunlock(&c->drawlk);
- rpc_flush(c, r);
- qlock(&c->drawlk);
+ qunlock(&drawlk);
+ c->impl->rpc_flush(c, r);
+ qlock(&drawlk);
rpc_gfxdrawlock();
}
}
@@ -614,7 +616,7 @@ drawcoord(uchar *p, uchar *maxp, int oldx, int *newx)
int
draw_dataread(Client *cl, void *a, int n)
{
- qlock(&cl->drawlk);
+ qlock(&drawlk);
if(cl->readdata == nil){
werrstr("no draw data");
goto err;
@@ -627,11 +629,11 @@ draw_dataread(Client *cl, void *a, int n)
memmove(a, cl->readdata, cl->nreaddata);
free(cl->readdata);
cl->readdata = nil;
- qunlock(&cl->drawlk);
+ qunlock(&drawlk);
return n;
err:
- qunlock(&cl->drawlk);
+ qunlock(&drawlk);
return -1;
}
@@ -656,7 +658,7 @@ draw_datawrite(Client *client, void *v, int n)
Refreshfn reffn;
Refx *refx;
- qlock(&client->drawlk);
+ qlock(&drawlk);
rpc_gfxdrawlock();
a = v;
m = 0;
@@ -1431,7 +1433,7 @@ draw_datawrite(Client *client, void *v, int n)
}
}
rpc_gfxdrawunlock();
- qunlock(&client->drawlk);
+ qunlock(&drawlk);
return oldn - n;
Enodrawimage:
@@ -1502,6 +1504,6 @@ Ebadarg:
error:
werrstr("%s", err);
rpc_gfxdrawunlock();
- qunlock(&client->drawlk);
+ qunlock(&drawlk);
return -1;
}
diff --git a/src/cmd/devdraw/devdraw.h b/src/cmd/devdraw/devdraw.h
index 6829ab32..261d04d1 100644
--- a/src/cmd/devdraw/devdraw.h
+++ b/src/cmd/devdraw/devdraw.h
@@ -7,6 +7,7 @@ typedef struct Mousebuf Mousebuf;
typedef struct Tagbuf Tagbuf;
typedef struct Client Client;
+typedef struct ClientImpl ClientImpl;
typedef struct DImage DImage;
typedef struct DScreen DScreen;
typedef struct CScreen CScreen;
@@ -43,6 +44,20 @@ struct Tagbuf
int wi;
};
+struct ClientImpl
+{
+ void (*rpc_resizeimg)(Client*);
+ void (*rpc_resizewindow)(Client*, Rectangle);
+ void (*rpc_setcursor)(Client*, Cursor*, Cursor2*);
+ void (*rpc_setlabel)(Client*, char*);
+ void (*rpc_setmouse)(Client*, Point);
+ void (*rpc_topwin)(Client*);
+ void (*rpc_bouncemouse)(Client*, Mouse);
+ void (*rpc_flush)(Client*, Rectangle);
+};
+
+extern QLock drawlk;
+
struct Client
{
int rfd;
@@ -56,10 +71,9 @@ struct Client
char* wsysid;
- // drawlk protects the draw data structures.
+ // drawlk protects the draw data structures for all clients.
// It can be acquired by an RPC thread or a graphics thread
// but must not be held on one thread while waiting for the other.
- QLock drawlk;
/*Ref r;*/
DImage* dimage[NHASH];
CScreen* cscreen;
@@ -82,6 +96,7 @@ struct Client
int nname;
DName* name;
int namevers;
+ ClientImpl* impl;
// Only accessed/modified by the graphics thread.
const void* view;
@@ -196,17 +211,8 @@ void gfx_started(void);
Memimage *rpc_attach(Client*, char*, char*);
char* rpc_getsnarf(void);
void rpc_putsnarf(char*);
-void rpc_resizeimg(Client*);
-void rpc_resizewindow(Client*, Rectangle);
-void rpc_serve(Client*);
-void rpc_setcursor(Client*, Cursor*, Cursor2*);
-void rpc_setlabel(Client*, char*);
-void rpc_setmouse(Client*, Point);
void rpc_shutdown(void);
-void rpc_topwin(Client*);
void rpc_main(void);
-void rpc_bouncemouse(Client*, Mouse);
-void rpc_flush(Client*, Rectangle);
// rpc_gfxdrawlock and rpc_gfxdrawunlock
// are called around drawing operations to lock and unlock
diff --git a/src/cmd/devdraw/latin1.c b/src/cmd/devdraw/latin1.c
index a3d13a08..87c0be45 100644
--- a/src/cmd/devdraw/latin1.c
+++ b/src/cmd/devdraw/latin1.c
@@ -17,16 +17,15 @@ static struct cvlist
};
/*
- * Given 5 characters k[0]..k[4], find the rune or return -1 for failure.
+ * Given 5 characters k[0]..k[n], find the rune or return -1 for failure.
*/
static long
-unicode(Rune *k)
+unicode(Rune *k, int n)
{
long i, c;
- k++; /* skip 'X' */
c = 0;
- for(i=0; i<4; i++,k++){
+ for(i=0; i<n; i++,k++){
c <<= 4;
if('0'<=*k && *k<='9')
c += *k-'0';
@@ -36,6 +35,8 @@ unicode(Rune *k)
c += 10 + *k-'A';
else
return -1;
+ if(c > Runemax)
+ return -1;
}
return c;
}
@@ -53,10 +54,32 @@ latin1(Rune *k, int n)
char* p;
if(k[0] == 'X'){
- if(n>=5)
- return unicode(k);
- else
- return -5;
+ if(n < 2)
+ return -2;
+ if(k[1] == 'X') {
+ if(n < 3)
+ return -3;
+ if(k[2] == 'X') {
+ if(n < 9) {
+ if(unicode(k+3, n-3) < 0)
+ return -1;
+ return -(n+1);
+ }
+ return unicode(k+3, 6);
+ }
+ if(n < 7) {
+ if(unicode(k+2, n-2) < 0)
+ return -1;
+ return -(n+1);
+ }
+ return unicode(k+2, 5);
+ }
+ if(n < 5) {
+ if(unicode(k+1, n-1) < 0)
+ return -1;
+ return -(n+1);
+ }
+ return unicode(k+1, 4);
}
for(l=latintab; l->ld!=0; l++)
diff --git a/src/cmd/devdraw/mac-screen.m b/src/cmd/devdraw/mac-screen.m
index c6e58341..ad9c029e 100644
--- a/src/cmd/devdraw/mac-screen.m
+++ b/src/cmd/devdraw/mac-screen.m
@@ -37,6 +37,26 @@ static void setprocname(const char*);
static uint keycvt(uint);
static uint msec(void);
+static void rpc_resizeimg(Client*);
+static void rpc_resizewindow(Client*, Rectangle);
+static void rpc_setcursor(Client*, Cursor*, Cursor2*);
+static void rpc_setlabel(Client*, char*);
+static void rpc_setmouse(Client*, Point);
+static void rpc_topwin(Client*);
+static void rpc_bouncemouse(Client*, Mouse);
+static void rpc_flush(Client*, Rectangle);
+
+static ClientImpl macimpl = {
+ rpc_resizeimg,
+ rpc_resizewindow,
+ rpc_setcursor,
+ rpc_setlabel,
+ rpc_setmouse,
+ rpc_topwin,
+ rpc_bouncemouse,
+ rpc_flush
+};
+
@class DrawView;
@class DrawLayer;
@@ -201,6 +221,7 @@ rpc_attach(Client *c, char *label, char *winsize)
{
LOG(@"attachscreen(%s, %s)", label, winsize);
+ c->impl = &macimpl;
dispatch_sync(dispatch_get_main_queue(), ^(void) {
@autoreleasepool {
DrawView *view = [[DrawView new] attach:c winsize:winsize label:label];
@@ -302,7 +323,7 @@ rpc_attach(Client *c, char *label, char *winsize)
// rpc_topwin moves the window to the top of the desktop.
// Called from an RPC thread with no client lock held.
-void
+static void
rpc_topwin(Client *c)
{
DrawView *view = (__bridge DrawView*)c->view;
@@ -319,7 +340,7 @@ rpc_topwin(Client *c)
// rpc_setlabel updates the client window's label.
// If label == nil, the call is a no-op.
// Called from an RPC thread with no client lock held.
-void
+static void
rpc_setlabel(Client *client, char *label)
{
DrawView *view = (__bridge DrawView*)client->view;
@@ -344,7 +365,7 @@ rpc_setlabel(Client *client, char *label)
// rpc_setcursor updates the client window's cursor image.
// Either c and c2 are both non-nil, or they are both nil to use the default arrow.
// Called from an RPC thread with no client lock held.
-void
+static void
rpc_setcursor(Client *client, Cursor *c, Cursor2 *c2)
{
DrawView *view = (__bridge DrawView*)client->view;
@@ -460,7 +481,7 @@ rpc_setcursor(Client *client, Cursor *c, Cursor2 *c2)
// rpc_flush flushes changes to view.img's rectangle r
// to the on-screen window, making them visible.
// Called from an RPC thread with no client lock held.
-void
+static void
rpc_flush(Client *client, Rectangle r)
{
DrawView *view = (__bridge DrawView*)client->view;
@@ -474,17 +495,17 @@ rpc_flush(Client *client, Rectangle r)
if(!rectclip(&r, Rect(0, 0, self.dlayer.texture.width, self.dlayer.texture.height)) || !rectclip(&r, self.img->r))
return;
- // self.client->drawlk protects the pixel data in self.img.
+ // drawlk protects the pixel data in self.img.
// In addition to avoiding a technical data race,
// the lock avoids drawing partial updates, which makes
// animations like sweeping windows much less flickery.
- qlock(&self.client->drawlk);
+ qlock(&drawlk);
[self.dlayer.texture
replaceRegion:MTLRegionMake2D(r.min.x, r.min.y, Dx(r), Dy(r))
mipmapLevel:0
withBytes:byteaddr(self.img, Pt(r.min.x, r.min.y))
bytesPerRow:self.img->width*sizeof(u32int)];
- qunlock(&self.client->drawlk);
+ qunlock(&drawlk);
NSRect nr = NSMakeRect(r.min.x, r.min.y, Dx(r), Dy(r));
dispatch_time_t time;
@@ -506,7 +527,7 @@ rpc_flush(Client *client, Rectangle r)
// rpc_resizeimg forces the client window to discard its current window and make a new one.
// It is called when the user types Cmd-R to toggle whether retina mode is forced.
// Called from an RPC thread with no client lock held.
-void
+static void
rpc_resizeimg(Client *c)
{
DrawView *view = (__bridge DrawView*)c->view;
@@ -541,7 +562,7 @@ rpc_resizeimg(Client *c)
// rpc_resizewindow asks for the client window to be resized to size r.
// Called from an RPC thread with no client lock held.
-void
+static void
rpc_resizewindow(Client *c, Rectangle r)
{
DrawView *view = (__bridge DrawView*)c->view;
@@ -696,7 +717,7 @@ rpc_resizewindow(Client *c, Rectangle r)
// rpc_setmouse moves the mouse cursor.
// Called from an RPC thread with no client lock held.
-void
+static void
rpc_setmouse(Client *c, Point p)
{
DrawView *view = (__bridge DrawView*)c->view;
@@ -1095,7 +1116,7 @@ rpc_putsnarf(char *s)
// rpc_bouncemouse is for sending a mouse event
// back to the X11 window manager rio(1).
// Does not apply here.
-void
+static void
rpc_bouncemouse(Client *c, Mouse m)
{
}
diff --git a/src/cmd/devdraw/mklatinkbd.c b/src/cmd/devdraw/mklatinkbd.c
index db34b6ec..50dd26b0 100644
--- a/src/cmd/devdraw/mklatinkbd.c
+++ b/src/cmd/devdraw/mklatinkbd.c
@@ -191,7 +191,7 @@ readfile(char *fname)
r = strtol(line, nil, 16);
p = strchr(line, ' ');
- if(r == 0 || p != line+4 || p[0] != ' ' || p[1] != ' ') {
+ if(r == 0 || (p != line+4 && p != line+5) || p[0] != ' ' || (p == line+4 && p[1] != ' ')) {
fprint(2, "%s:%d: cannot parse line\n", fname, lineno);
continue;
}
diff --git a/src/cmd/devdraw/srv.c b/src/cmd/devdraw/srv.c
index 570091bc..05a08fda 100644
--- a/src/cmd/devdraw/srv.c
+++ b/src/cmd/devdraw/srv.c
@@ -54,6 +54,7 @@ threadmain(int argc, char **argv)
usage();
}ARGEND
+ memimageinit();
fmtinstall('H', encodefmt);
if((p = getenv("DEVDRAWTRACE")) != nil)
trace = atoi(p);
@@ -202,8 +203,11 @@ runmsg(Client *c, Wsysmsg *m)
break;
case Tinit:
- memimageinit();
i = rpc_attach(c, m->label, m->winsize);
+ if(i == nil) {
+ replyerror(c, m);
+ break;
+ }
draw_initdisplaymemimage(c, i);
replymsg(c, m);
break;
@@ -225,6 +229,7 @@ runmsg(Client *c, Wsysmsg *m)
break;
case Trdkbd:
+ case Trdkbd4:
qlock(&c->eventlk);
if((c->kbdtags.wi+1)%nelem(c->kbdtags.t) == c->kbdtags.ri) {
qunlock(&c->eventlk);
@@ -232,7 +237,7 @@ runmsg(Client *c, Wsysmsg *m)
replyerror(c, m);
break;
}
- c->kbdtags.t[c->kbdtags.wi++] = m->tag;
+ c->kbdtags.t[c->kbdtags.wi++] = (m->tag<<1) | (m->type==Trdkbd4);
if(c->kbdtags.wi == nelem(c->kbdtags.t))
c->kbdtags.wi = 0;
c->kbd.stall = 0;
@@ -241,35 +246,35 @@ runmsg(Client *c, Wsysmsg *m)
break;
case Tmoveto:
- rpc_setmouse(c, m->mouse.xy);
+ c->impl->rpc_setmouse(c, m->mouse.xy);
replymsg(c, m);
break;
case Tcursor:
if(m->arrowcursor)
- rpc_setcursor(c, nil, nil);
+ c->impl->rpc_setcursor(c, nil, nil);
else {
scalecursor(&m->cursor2, &m->cursor);
- rpc_setcursor(c, &m->cursor, &m->cursor2);
+ c->impl->rpc_setcursor(c, &m->cursor, &m->cursor2);
}
replymsg(c, m);
break;
case Tcursor2:
if(m->arrowcursor)
- rpc_setcursor(c, nil, nil);
+ c->impl->rpc_setcursor(c, nil, nil);
else
- rpc_setcursor(c, &m->cursor, &m->cursor2);
+ c->impl->rpc_setcursor(c, &m->cursor, &m->cursor2);
replymsg(c, m);
break;
case Tbouncemouse:
- rpc_bouncemouse(c, m->mouse);
+ c->impl->rpc_bouncemouse(c, m->mouse);
replymsg(c, m);
break;
case Tlabel:
- rpc_setlabel(c, m->label);
+ c->impl->rpc_setlabel(c, m->label);
replymsg(c, m);
break;
@@ -306,12 +311,12 @@ runmsg(Client *c, Wsysmsg *m)
break;
case Ttop:
- rpc_topwin(c);
+ c->impl->rpc_topwin(c);
replymsg(c, m);
break;
case Tresize:
- rpc_resizewindow(c, m->rect);
+ c->impl->rpc_resizewindow(c, m->rect);
replymsg(c, m);
break;
}
@@ -353,13 +358,17 @@ replymsg(Client *c, Wsysmsg *m)
static void
matchkbd(Client *c)
{
+ int tag;
Wsysmsg m;
if(c->kbd.stall)
return;
while(c->kbd.ri != c->kbd.wi && c->kbdtags.ri != c->kbdtags.wi){
+ tag = c->kbdtags.t[c->kbdtags.ri++];
m.type = Rrdkbd;
- m.tag = c->kbdtags.t[c->kbdtags.ri++];
+ if(tag&1)
+ m.type = Rrdkbd4;
+ m.tag = tag>>1;
if(c->kbdtags.ri == nelem(c->kbdtags.t))
c->kbdtags.ri = 0;
m.rune = c->kbd.r[c->kbd.ri++];
@@ -513,7 +522,7 @@ gfx_keystroke(Client *c, int ch)
else
c->forcedpi = 225;
qunlock(&c->eventlk);
- rpc_resizeimg(c);
+ c->impl->rpc_resizeimg(c);
return;
}
if(!c->kbd.alting){
diff --git a/src/cmd/devdraw/x11-screen.c b/src/cmd/devdraw/x11-screen.c
index 62f49f2f..0bbc25d6 100644
--- a/src/cmd/devdraw/x11-screen.c
+++ b/src/cmd/devdraw/x11-screen.c
@@ -40,6 +40,26 @@ static void _xmovewindow(Xwin *w, Rectangle r);
static int _xtoplan9kbd(XEvent *e);
static int _xselect(XEvent *e);
+static void rpc_resizeimg(Client*);
+static void rpc_resizewindow(Client*, Rectangle);
+static void rpc_setcursor(Client*, Cursor*, Cursor2*);
+static void rpc_setlabel(Client*, char*);
+static void rpc_setmouse(Client*, Point);
+static void rpc_topwin(Client*);
+static void rpc_bouncemouse(Client*, Mouse);
+static void rpc_flush(Client*, Rectangle);
+
+static ClientImpl x11impl = {
+ rpc_resizeimg,
+ rpc_resizewindow,
+ rpc_setcursor,
+ rpc_setlabel,
+ rpc_setmouse,
+ rpc_topwin,
+ rpc_bouncemouse,
+ rpc_flush
+};
+
static Xwin*
newxwin(Client *c)
{
@@ -51,6 +71,7 @@ newxwin(Client *c)
w->client = c;
w->next = _x.windows;
_x.windows = w;
+ c->impl = &x11impl;
c->view = w;
return w;
}